2016-07-25 18 views
-1

У меня есть файл csv, который отформатирован следующим образом: id,text. Вот пример:В Java, как мне переписать определенную часть строки в файле?

helloText,How are you 
goodbyeMessage,Some new text for a change 
errorMessage,Oops something went wrong 

Теперь давайте говорить, например, я хочу, чтобы изменить текстовую часть goodbyeMessage которая Some new text for change, чтобы See you later

В результате csv должен выглядеть следующим образом:

helloText,How are you 
goodbyeMessage,See you later 
errorMessage,Oops something went wrong 

У меня есть код, который может записать файл, но когда код завершит выполнение, это файл csv:

helloText,How are you 
goodbyeMessage,Some new text for a change 
errorMessage,Oops something went wronggoodbyeMessage,See you later 

Я знаю, что это происходит потому, что я установил значение append файла FileWriter в значение true. Если я не все, то вытирается.

Я попытался использовать FileWriter.newLine(), чтобы он выглядел лучше, но это не то, чего я пытаюсь достичь. Я все еще хочу иметь такое же количество строк в файле. MyApp.java

public static void main(String[] args) throws FileNotFoundException, IOException { 
    PropsWriter pw = new PropsWriter("test_props.txt"); 
    pw.updateElementText("goodbyeMessage", "See you later"); 
} 

PropsWriter.java

/** 
* Updates the text of a given element in the properties file. 
* 
* @param id The id of the element 
* @param newText The text that will replace the original text. 
* 
* @throws IOException If I/O error occurs 
*/ 
public void updateElementText(String id, String newText) throws IOException { 
    Assertions.checkNotNull(id, "Id must not be null."); 
    Assertions.checkNotNull(id, "Id must not be an empty string."); 
    File file = new File(pathName); 
    BufferedReader br = new BufferedReader(new FileReader(file)); 
    BufferedWriter wr = new BufferedWriter(new FileWriter(file, true)); 
    try { 
     String line; 

     while((line = br.readLine()) != null) { 
      if(line.contains(id)) { 
       //returns true 
       System.out.println("Is line there: " + line.contains(id)); 

       //returns helloText 
       System.out.println("ID: " + extractId(line)); 

       //returns How are you 
       System.out.println("TEXT: " + extractText(line)); 

       //returns Some new text for a change 
       System.out.println("NEW_TEXT: " + newText); 

       // This is where I am trying to replace the old text 
       // with new text that came from the main method. 
       line = line.replaceAll(extractText(line), newText); 
       //wr.newLine(); 
       wr.write(line);    
      } 
     } 
    } catch(IOException e) { 
     e.printStackTrace(); 
    } finally { 
     wr.close(); 
    } 
} 

/** 
* Gets the id part of a line that is stored in the 
* properties file. 
* 
* @param element The element the id is got from. 
* @return String representation of the id. 
*/ 
private static String extractId(String line) { 
    final int commaOccurence = getFirstCommaOccurrence(line); 
    return line.substring(0, commaOccurence); 
} 

/** 
* Gets the text part of a line that is stored in the 
* properties file. 
* 
* @param element The element the text is got from. 
* @return String representation of the text. 
*/ 
private static String extractText(String line) { 
    final int commaOccurence = getFirstCommaOccurrence(line); 
    return line.substring(commaOccurence + 1, line.length()); 
} 

/** 
* Gets the first occurrence of a comma in any given line of a text file. 
* @param element 
* @return 
*/ 
private static int getFirstCommaOccurrence(String line) { 
    return line.indexOf(","); 
} 
+2

Вы только что сказали это. Не устанавливайте 'FileWriter' в' true' (поскольку он только добавляет новые вещи). Вам нужно прочитать весь файл, сохранить все строки (например, в «Список »). Затем вы манипулируете данными. А после этого вы переписываете ** весь текст ** (например, используя указанный «Список '). Однако, если вы точно знаете, какая строка должна быть добавлена ​​(и вам не нужно найти место), тогда вам может быть лучше, чем более низкоуровневый файловый писатель. – Zabuza

+0

Вы бы сделали то же самое, если файл будет содержать тысячи этих строк? – cod3min3

+0

Если вам нужно найти строку, вам нужно будет перебирать все строки. Возможно, вам не нужно сохранять все строки (если файл большой). Вы также можете запомнить точное место и использовать более низкоуровневый файл-писатель. Например, с помощью «RandomAccessFile»: https://examples.javacodegeeks.com/core-java/io/randomaccessfile/java-randomaccessfile-example – Zabuza

ответ

0

К сожалению, не существует на самом деле способ сделать это (что я знаю), кроме загрузки всех файлов данных в некоторый изменяемый объект, а затем записывая все это обратно в файл.

Files класс обеспечивает удобный способ для чтения всего файла в List


Как @Zabuza упоминалось в комментариях, Java предоставляет класс RandomAccessFile, который может перемещаться в определенном месте в файл и перезаписать байты. методы, которые могут представлять интерес для Вас будет:

  • getFilePointer() - Возвращает текущее смещение в файле
  • seek(long pos) - перемещает файл компенсировано pos
  • write(byte[] b) - пишет b в текущую позицию файла

Надеюсь, что это поможет

+0

'RandomAccessFile' может читать точную позицию, не изменяя материал до (но после): https: //examples.javacodegeeks.ком/ядро-Java/И.О./RandomAccessFile/Java-пример-RandomAccessFile – Zabuza

1

Вы только что сказали это. Не устанавливайте FileWriter в true (так как только добавляет новых вещей). Вам нужно прочитать весь файл, сохранить все строки (например, в List<String>). Затем вы манипулируете данными. А после этого вы переписываете весь текст (например, используя указанный List<String>).

В вашем коде выше это будет первым заменить true с false:

BufferedWriter wr = new BufferedWriter(new FileWriter(file, false)); 

Второй, всегда пишут в файл, а остальные строки затем затеряться:

if(line.contains(id)) { 
    ... 
    line = line.replaceAll(extractText(line), newText); 
} 
wr.write(line); 

Однако, если у вас очень большой файл и вы не хотите переписывать все строк, то вы можете пойти на более низкий уровень FileWriter, например RandomAccessFile. Эта концепция позволяет запускать манипуляции с файлами в заданной позиции без перезаписи всего, что было до этой позиции. Вы можете искать линию (или прыгать, если знаете, где), внести изменения. Но вам нужно будет переписать все, что приходит после изменение. Вот пример использования: RandomAccessFile example

Нет лучшего решения, так как это зависит от платформы. Более конкретно, это зависит от используемой файловой системы, например NTFS или FAT32 и так далее.
В общем, они хранят файл, разбивая его на несколько пакетов. Затем пакеты сохраняются на вашем жестком диске, они помещают их туда, где они лучше всего подходят. Файловая система сохраняет указатель на каждый стартовый пакет файла в master table. Затем каждый пакет сохраняет указатель на следующие пакеты и так далее до достижения EOF.

Вы видите, что легко изменить что-то посередине, не изменяя все, что было раньше. Но вам, вероятно, нужно изменить материал, который приходит после, поскольку вы не можете контролировать, как OS разбивает новые данные на пакеты. Если вы идете очень низкоуровневый, вы можете управлять отдельными пакетами и вводить данные без изменения всего после. Но я не думаю, что вы хотите это сделать :)