Capture data read from file into string stream Java - java

I'm coming from a C++ background, so be kind on my n00bish queries...
I'd like to read data from an input file and store it in a stringstream. I can accomplish this in an easy way in C++ using stringstreams. I'm a bit lost trying to do the same in Java.
Following is a crude code/way I've developed where I'm storing the data read line-by-line in a string array. I need to use a string stream to capture my data into (rather than use a string array).. Any help?
char dataCharArray[] = new char[2];
int marker=0;
String inputLine;
String temp_to_write_data[] = new String[100];
// Now, read from output_x into stringstream
FileInputStream fstream = new FileInputStream("output_" + dataCharArray[0]);
// Convert our input stream to a BufferedReader
BufferedReader in = new BufferedReader (new InputStreamReader(fstream));
// Continue to read lines while there are still some left to read
while ((inputLine = in.readLine()) != null )
{
// Print file line to screen
// System.out.println (inputLine);
temp_to_write_data[marker] = inputLine;
marker++;
}
EDIT:
I think what I really wanted was a StringBuffer.
I need to read data from a file (into a StringBuffer, probably) and write/transfer all the data back to another file.

In Java, first preference should always be given to buying code from the library houses:
http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html
http://commons.apache.org/io/api-1.4/org/apache/commons/io/FileUtils.html
In short, what you need is this:
FileUtils.readFileToString(File file)

StringBuffer is one answer, but if you're just writing it to another file, then you can just open an OutputStream and write it directly out to the other file. Holding a whole file in memory is probably not a good idea.

In you simply want to read a file and write another one:
BufferedInputStream in = new BufferedInputStream( new FileInputStream( "in.txt" ) );
BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( "out.txt" ) );
int b;
while ( (b = in.read()) != -1 ) {
out.write( b );
}
If you want to read a file into a string:
StringWriter out = new StringWriter();
BufferedReader in = new BufferedReader( new FileReader( "in.txt" ) );
int c;
while ( (c = in.read()) != -1 ) {
out.write( c );
}
StringBuffer buf = out.getBuffer();
This can be made more efficient if you read using byte arrays. But I recommend that you use the excellent apache common-io. IOUtils (http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html) will do the loop for you.
Also, you should remember to close the streams.

I also come from C++, and I was looking for a class similar to the C++ 'StringStreamReader', but I couldn't find it. In my case (which I think was very simple), I was trying to read a file line by line and then read a String and an Integer from each of these lines. My final solution was to use two objects of the class java.util.Scanner, so that I could use one of them to read the lines of the file directly to a String and use the second one to re-read the content of each line (now in the String) to the variables (a new String and a positive 'int'). Here's my code:
try {
//"path" is a String containing the path of the file we want to read
Scanner sc = new Scanner(new BufferedReader(new FileReader(new File(path))));
while (sc.hasNextLine()) { //while the file isn't over
Scanner scLine = new Scanner(sc.nextLine());
//sc.nextLine() returns the next line of the file into a String
//scLine will now proceed to scan (i.e. analyze) the content of the string
//and identify the string and the positive 'int' (what in C++ would be an 'unsigned int')
String s = scLine.next(); //this returns the string wanted
int x;
if (!scLine.hasNextInt() || (x = scLine.nextInt()) < 0) return false;
//scLine.hasNextInt() analyzes if the following pattern can be interpreted as an int
//scLine.nextInt() reads the int, and then we check if it is positive or not
//AT THIS POINT, WE ALREADY HAVE THE VARIABLES WANTED AND WE CAN DO
//WHATEVER WE WANT WITH THEM
//in my case, I put them into a HashMap called 'hm'
hm.put(s, x);
}
sc.close();
//we finally close the scanner to point out that we won't need it again 'till the next time
} catch (Exception e) {
return false;
}
return true;
Hope that helped.

Related

How to piece together String using file reader and char array

Wrote a file in another class and now I'm trying to piece together the file into a JLabel, so I need to convert the name in the file into a string. Using FileReader and a char array to separate each character into an array to be put together in the JLabel.
I'm getting this error on NamePieces[x] = (char)nr;:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at clients.initialize(clients.java:197)
at clients.<init>(clients.java:72)
This is the code that I want to read the file:
try(FileReader nameReader = new FileReader(NamePath)) {
int nr = nameReader.read();
int x = 0;
while(nr != -1) {
namePieces[x] = (char)nr;
nr = nameReader.read();
x++;
}
}
catch (FileNotFoundException e) {}
catch (IOException e1) {}
String name = String.valueOf(namePieces[0]) + namePieces[1];
Doesn't work
Most likely, your problem occurs because namePieces is not initialized. As was already mentioned in the comments, you should not use char[] as a container for your characters (because in real world you won't know the length of the files' contents every time, so you will probably need to resize your container), it is way more better to use StringBuilder, provided by Java standard library. It will protect you from getting out of bounds.
StringBuilder namePieces = new StringBuilder();
File file = new File(filePath);
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(file),
Charset.forName("UTF-8")));
int c;
while((c = reader.read()) != -1) {
namePieces.append((char) c);
}
String nameString = namePieces.toString(); // Use this string as a complete array of needed characters
As you see I changed an approach by using not only StringBuilder, but also BufferedReader. However, for your task you can leave FileReader as it is. Just consider appending characters to builder.
If your file just contains a String there is a straightforward way to read it:
public String readMyFile( String fileName) throws IOException {
Path path = Paths.get(fileName);
return Files.readAllLines(path).get(0);
}

Java - open txt file and clear all multiple spaces

I have a txt file and what I am trying to do is open it and delete all multiple spaces so they become only one. I use:
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two.txt"));
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
}
br.close();
bw.close();
However, as it seems correct according to me at least, nothing is written on the file. If I use a system.out.println command, it is not printed, meaning that execution is never in the while loop... What do I do wrong? Thanks
you are reading the file and at the same time writing contents on it..it is not allowed...
so better way to read the file first and store the processed text in another file and finally replace the original file with the new one..try this
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two_copy.txt"));
String current_line;
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
bw.newLine();
}
br.close();
bw.close();
File copyFile = new File("C:\\Users\\Chris\\Desktop\\file_two_copy.txt");
File originalFile = new File("C:\\Users\\Chris\\Desktop\\file_two.txt");
originalFile.delete();
copyFile.renameTo(originalFile);
it may help...
There are few problems with your approach:
Main one is that you are trying to read and write to same file at the same time.
other is that new FileWriter(..) always creates new empty file which kind of prevents FileReader from reading anything from your file.
You should read content from file1 and write its modified version in file2. After that replace file1 with file2.
Your code can look more or less like
Path input = Paths.get("input.txt");
Path output = Paths.get("output.txt");
List<String> lines = Files.readAllLines(input);
lines.replaceAll(line -> line.replaceAll("\\s+", " "));
Files.write(output, lines);
Files.move(output, input, StandardCopyOption.REPLACE_EXISTING);
You must read first then write, you are not allowed to read and write to the same file at the same time, you would need to use RandomAccessFile to do that.
If you don't want to learn a new technique, you will need to either write to a separate file, or cache all lines to memory(IE an ArrayList) but you must close the BufferedReader before you Initialize your BufferedWriter, or it will get a file access error.
Edit:
In case you want to look into it, here is a RandomAccessFile use case example for your intended use. It is worth pointing out this will only work if the final line length is less than or equal to the original, because this technique is basically overwriting the existing text, but should be very fast with a small memory overhead and would work on extremely large files:
public static void readWrite(File file) throws IOException{
RandomAccessFile raf = new RandomAccessFile(file, "rw");
String newLine = System.getProperty("line.separator");
String line = null;
int write_pos = 0;
while((line = raf.readLine()) != null){
line = line.replaceAll("\\s+", " ") + newLine;
byte[] bytes = line.getBytes();
long read_pos = raf.getFilePointer();
raf.seek(write_pos);
raf.write(bytes, 0, bytes.length);
write_pos += bytes.length;
raf.seek(read_pos);
}
raf.setLength(write_pos);
raf.close();
}

Replace 2nd Occurrence of Word in Text File

I have a sentence in my text file,
Moreover, human serum could significantly enhance the LPS-induced DV suppression in a CD14-dependent manner, indicating that the "binding" of LPS to CD14 was critical for the induction of virus inhibition.
How do I replace the 2nd occurrence of CD14 to AB45 and write back to the text file?
For the algorithm itself,
file.indexOf("CD14", file.indexOf("CD14")+4)
can be used to locate the occurance (given that "file" is a string with all of the contents of your file). The second argument of "indexOf" asks for a start point. By calling indexOf twice, you find the first instance of the string than check for another instance skipping past the first instance (+4 since indexOf will return the start of the string, adding the length of the string skips over it). To replace the string,
int i = file.indexOf("CD14", file.indexOf("CD14")+4);
String s = file;
if(i != -1) s = file.substring(0,i) + "AD25" + file.substring(Math.min(i+4,file.length()), file.length());
If you're asking how to read/write a text file, try google. one example - Java: How to read a text file , another - http://www.javapractices.com/topic/TopicAction.do?Id=42
There are several approaches to take in solving this one. A very simple but verbose approach would be:
public static void replaceSecondOccurence(String originalText, String replacementText) throws IOException {
File file = new File("file.txt");
InputStreamReader reader = new InputStreamReader(new FileInputStream(file));
StringBuilder fileContent = new StringBuilder();
int content;
while ((content = reader.read()) != -1) {
fileContent.append((char) content);
}
reader.close();
int index = fileContent.lastIndexOf(originalText);
fileContent.replace(index, index + originalText.length(), replacementText);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file));
writer.write(fileContent.toString());
writer.close();
}

Why does this take so long to run?

I'm a newbie to java, and I'm reading in a ~25 MB file, and it takes forever to just load... Are there any alternatives to make this faster? Is it the Scanner that can't handle large files?
String text = "";
Scanner sc = new Scanner(new File("text.txt"));
while(sc.hasNext()) {
text += sc.next();
}
You are concatenating to text every iteration, and Strings are immutable in Java. This means it creates a new String object in memory every time text is "modified," resulting in long load times for large files. You should always try and use a StringBuilder when you are continuously altering a String.
You could do:
StringBuilder text = new StringBuilder();
Scanner sc = new Scanner(new File("text.txt");
while(sc.hasNext()) {
text.append(sc.next());
}
When you want to access the contents of text, you can call text.toString().
It is the String +=, which creates everytime an evergrowing new String object.
In fact for smaller than 25 MB one could do (undermore):
StringBuilder sb = new StringBuilder();
BufferReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(new File("text.txt"), "UTF-8")));
for (;;) {
String line = in.readLine();
if (line == null)
break;
sb.append(line).append("\n");
}
in.close();
String text = sb.toString();
readLine yields the line upto the newline character(s), not including them.
In Java 7 one could do:
Path path = Paths.get("text.txt");
String text = new String(Files.readAllBytes(path), "UTF-8");
The encoding is given explicitly, as UTF-8. "Windows-1252" would be for Windows Latin-1 etcetera.
Try to use BufferedStreams, e.g, BufferedInputStream, BufferedReader they will accelerate it. For more information about BufferedStreams take a look at here;
http://docs.oracle.com/javase/tutorial/essential/io/buffers.html
And instead of String use StringBuilder since Strings are immutable in Java, it will create a new String within each iteration of while loop

Java create strings from Buffered Reader and compare Strings

I am using Java + Selenium 1 to test a web application.
I have to read through a text file line by line using befferedreader.readLine and compare the data that was found to another String.
Is there way to assign each line a unique string? I think it would be something like this:
FileInputStream fstream = new FileInputStream("C:\\write.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
String[] strArray = null;
int p=0;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strArray[p] = strLine;
assertTrue(strArray[p].equals(someString));
p=p+1;
}
The problem with this is that you don't know how many lines there are, so you can't size your array correctly. Use a List<String> instead.
In order of decreasing importance,
You don't need to store the Strings in an array at all, as pointed out by Perception.
You don't know how many lines there are, so as pointed out by Qwerky, if you do need to store them you should use a resizeable collection like ArrayList.
DataInputStream is not needed: you can just wrap your FileInputStream directly in an InputStreamReader.
You may want to try something like:
public final static String someString = "someString";
public boolean isMyFileOk(String filename){
Scanner sc = new Scanner(filename);
boolean fileOk = true;
while(sc.hasNext() && fileOk){
String line = sc.nextLine();
fileOk = isMyLineOk(line);
}
sc.close();
return fileOk;
}
public boolean isMyLineOk(String line){
return line.equals(someString);
}
The Scanner class is usually a great class to read files :)
And as suggested, you may check one line at a time instead of loading them all in memory before processing them. This may not be an issue if your file is relatively small but you better keep your code scalable, especially for doing the exact same thing :)

Categories