Should I Use Streams or Readers/Writers to Copy a Text File?

In summary, the conversation discusses the need for assistance with a Java assignment involving input and output. The expert advises using the BufferedReader class and the readLine() method to read the contents of a file into a string. The necessary steps to count the number of lines, words, and characters in the file are explained, including using a StringTokenizer to count the tokens. The expert also suggests making use of a lineCount variable and a wordCount variable in addition to the charCount variable to make the counting process easier. The conversation ends with the expert giving a hierarchy of input and output concepts, but the individual is still confused and asks for further explanation.
  • #1
muna580
Please, I am in desprate need of soemoen that knows java. I need to turn in an assigment in 2 hours and I am trying to figure out something that I don't udnerstad. We are currently doing input and output stuff. I am trying to figure out how to count the numerb of lines, words, and chars in a given file.
 
Technology news on Phys.org
  • #2
Well, first step is to read the contents of the file into a string. Use the BufferedReader.readLine() method. Figuring out how this works directly from Java's API can take a while, but if you do a search for "Java read file" on Google you can get plenty of examples. The necessary line is going to be something like:
BufferedReader b = new BufferedReader(new FileInputStream(myfile));
Then you want to loop through all the lines in b, using b.readLine(). Keep counters for the number of lines, words, and characters, and every time you read a line simply increase the line count by 1 and increase the character count by the length of the line plus one (since newline is a character). To count the number of words you will need to make a StringTokenizer of the line and count the number of tokens.
 
  • #3
How do I check if there are more lines? I used this but I am not sure if it is right

Code:
	public static int countChar(File f)
	{
		int charCount = 0;
		
		try
		{
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			
			while (br.readLine() != null)
			{
				String stringRead = br.readLine();
					
				StringTokenizer st = new StringTokenizer(stringRead);
				
				while (st.hasMoreTokens())
				{
					charCount += (st.nextToken()).length();
				}
				
			}
			
			br.close();
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
		
		return charCount;
	}
 
  • #4
muna580 said:
Code:
	public static int countChar(File f)
	{
		int charCount = 0;
		
		try
		{
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			
			while (br.readLine() != null)
			{
				String stringRead = br.readLine();
Here you are reading the line twice--that's two calls to br.readLine() you have here. That's not what you want, and indeed it might cause you to go past the end of the file. Instead you should say
Code:
			while ((stringRead = br.readLine()) != null)
			{
This will read the line only once, and put the value into stringRead, and also test to see if the line is null, all in one line.
Code:
				StringTokenizer st = new StringTokenizer(stringRead);
				
				while (st.hasMoreTokens())
				{
					charCount += (st.nextToken()).length();
The total number of characters in the file is not the combined length of all the tokens. "the cat" has seven characters, not 6. Instead of counting the token lengths, you should say
charCount += stringRead.length() + 1;
where the +1 is to include the newline character. For this, you should start charCount at -1 not 0 because the last line has no newline after it.
Code:
				}
				
			}
			
			br.close();
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
		
		return charCount;
	}
By the way, it will be easier to count all three lengths at the same time. In addition to having a charCount variable, you should have a lineCount variable that you increase by 1 at each step (every time you read a line), and a wordCount variable that you increase by 1 for each token. You can return them in an array.
 
  • #5
I am still a little bit confused. The professor told me to do this

(f) Determine the number of lines in the file, the number of words in the file, and the number of characters in the file. The program should output a line saying something like this:

File: xxx.txt has 120 lines, 317 words, 4154 characters
(Use the class StreamTokenizer for this section)

But I am still having problems and don't understand how to do it. Before you reply to my topic, please read this method I wrote.

Edit:

It is too late to turn in the assignment, but I don't really care about that. I want to just understand this whole concept of I/O. Please can you help me understand it ? My teacher gave us like a I/O tree, it has like all the things listed InputStream, FIleInputStream, FilterINputStrea...

But I just don't undrrstand this whole concept.


Code:
	public static int countLines(File f)
	{
		int lineCount = 0;
		
		try
		{
			FileReader fr = new FileReader(f);
			StreamTokenizer s = new StreamTokenizer(fr);
			
			s.eolIsSignificant(true);
			
			while(s.nextToken() != s.TT_EOF)
			{
				lineCount = s.lineno();
			}
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
		return lineCount;
	}
	
	// coutns the numebr of words
		public static int countWords(File f)
	{
		int wordCount = 0;
		
		try
		{
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			
			String x = br.readLine();
			
			while (x != null)
			{
				String stringRead = x;
					
				StringTokenizer st = new StringTokenizer(stringRead);
				
				while (st.hasMoreTokens())
				{
					st.nextToken();
					wordCount++;
				}
				
				x = br.readLine();
				
			}
			
			br.close();
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
		
		return wordCount;
	}
	
	public static int countChar(File f)
	{
		int charCount = 0;
		
		try
		{
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			
			String x = br.readLine();
			
			while (x != null)
			{
				String stringRead = x;
					
				StringTokenizer st = new StringTokenizer(stringRead);
				
				while (st.hasMoreTokens())
				{
					charCount += (st.nextToken()).length();
				}
				
				x = br.readLine();
			}
			
			br.close();
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
		
		return charCount;
	}
 
Last edited by a moderator:
  • #6
Well, your code is mostly ok. You just are going to be slightly off on your character count since you're not counting spaces or newlines.

First, there are input streams, which is just data coming in from a file or the keyboard. System.in is a probably familiar example of a stream. Then, there are input readers, which can actually deal with that data. Your FileReader and BufferedReader are examples of that. Then there are Strings, which is what Readers read. What specifically are you unclear on?

You really should condense those 3 functions into just 1 function:
int[] countLinesCharactersWords(File f)
that goes through the file in one pass and counts everything. It only takes a few alterations of your countCharacters or countWords to make that function.
 
  • #7
I am still confused about this whole I/O concept. My professor gave me an hierarchy of all the things related to I/O. But I am a little confused. Below is someing my teacher gave me.

io-hierarchy.gif


First of all, I am confused about the RED part and the BLUE part. What is the diffrence? How do you know which one to use and how to use it?

Please expalin me the above so I can ask you my next question.
 
  • #8
The blue parts are streams and the red parts are readers/writers. Streams are just raw flows of data, just bytes. Readers and Writers take a stream and interpret it as characters, and provide methods for reading and writing to the stream as characters, not bytes.
 
  • #9
Can you give me an example of Reader/Writers taking streams and interpreting as characaters? How come I don't use the streams use playing around with .txt files? How some when I use .txt file, I just go strait to FileReader? When do I use INputStreamReader?

Also, how do I know when to put a try/catch statement in my coding with I/O. And how do do I know which one to catch. I mean, how do I know which one to choose when catching?

Like which of the following do I choose?

catch(IOException ioe)
{
ioe.printStackTrace();
}

catch(IOEception e)
{
System.out.println(e.toString());
}Also, I rewrote teh meathod to count the lines, words and char. Do you think it is correct? I dont' think its correct. I copied and pasted teh text from the txt file to ms words and did the word count and I get diffrent numbers.

Code:
	// Method countLineWordChar counts the number of lines, words, and chars, in 
	// a file given as a parameter. This method returns an array of intergers. In 
	// the array, the first position is the amount of lines, the second posistion 
	// is the amount of words, and the third is the amount of chars. 
	public static int[] countLineWordChar(File f)
	{
		int[] countInfo = new int[3]; 
		int lineCount = 0;
		int wordCount = 0;
		int charCount = 0; 
		
		try 
		{
			FileReader fr = new FileReader(f);
			StreamTokenizer st = new StreamTokenizer(fr);
			
			st.eolIsSignificant(true);
			
			while(st.nextToken() != StreamTokenizer.TT_EOF)
			{
				switch(st.ttype)
				{
					case StreamTokenizer.TT_WORD:
					wordCount++;
					String wordRead = st.sval; 
					charCount += wordRead.length();
					break;
					
					case StreamTokenizer.TT_EOL:
					lineCount++;
					break;
					
					default:
					break;
				}
			}
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
			
		countInfo[0] = lineCount;
		countInfo[1] = wordCount;
		countInfo[2] = charCount;
		
		return countInfo;
		
	}
	
	// Based on the countLineWordChar method, returns the amount of lines.
	public static int getLineCount(int[] countInfo)
	{
		return countInfo[0]; 
	}
	
	// Based on the countLineWordChar method, returns the amount of words.
	public static int getWordCount(int[] countInfo)
	{
		return countInfo[1]; 
	}
	
	// Based on the countLineWordChar method, returns the amount of chars.
	public static int getCharCount(int[] countInfo)
	{
		return countInfo[2]; 
	}
 
Last edited by a moderator:
  • #10
muna580 said:
Can you give me an example of Reader/Writers taking streams and interpreting as characaters? How come I don't use the streams use playing around with .txt files? How some when I use .txt file, I just go strait to FileReader? When do I use INputStreamReader?
Well, FileReader is just a convenience class. Basically,
FileReader f = new FileReader(file);
is roughly similar to saying
InputStreamReader f = new InputStreamReader(new FileInputStream(file));
but using the FileReader is shorter and a bit more convenient.
Also, how do I know when to put a try/catch statement in my coding with I/O. And how do do I know which one to catch. I mean, how do I know which one to choose when catching?

Like which of the following do I choose?

catch(IOException ioe)
{
ioe.printStackTrace();
}

catch(IOEception e)
{
System.out.println(e.toString());
}
That depends entirely on what information you want to know about the exception. The printStackTrace() will give you the description of the problem as well as information about where the problem occurred, and the toString() will give you just the description of the problem. Basically in I/O anytime you do any reading or writing, you'll probably run the risk of an IOException. If you use Eclipse to write your code, it will remind you to put try/catch blocks if you've forgotten them.

Also, I rewrote teh meathod to count the lines, words and char. Do you think it is correct? I dont' think its correct. I copied and pasted teh text from the txt file to ms words and did the word count and I get diffrent numbers.

Code:
	// Method countLineWordChar counts the number of lines, words, and chars, in 
	// a file given as a parameter. This method returns an array of intergers. In 
	// the array, the first position is the amount of lines, the second posistion 
	// is the amount of words, and the third is the amount of chars. 
	public static int[] countLineWordChar(File f)
	{
		int[] countInfo = new int[3]; 
		int lineCount = 0;
		int wordCount = 0;
		int charCount = 0; 
		
		try 
		{
			FileReader fr = new FileReader(f);
			StreamTokenizer st = new StreamTokenizer(fr);
			
			st.eolIsSignificant(true);
			
			while(st.nextToken() != StreamTokenizer.TT_EOF)
			{
				switch(st.ttype)
				{
					case StreamTokenizer.TT_WORD:
					wordCount++;
					String wordRead = st.sval; 
					charCount += wordRead.length();
					break;
					
					case StreamTokenizer.TT_EOL:
					lineCount++;
					break;
					
					default:
					break;
				}
			}
		}
		catch (FileNotFoundException fnfe)
		{
			UserInterface.showFileNotFoundError();
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, ioe.toString(), "Error", 
			JOptionPane.ERROR_MESSAGE);
		}
			
		countInfo[0] = lineCount;
		countInfo[1] = wordCount;
		countInfo[2] = charCount;
		
		return countInfo;
		
	}
	
	// Based on the countLineWordChar method, returns the amount of lines.
	public static int getLineCount(int[] countInfo)
	{
		return countInfo[0]; 
	}
	
	// Based on the countLineWordChar method, returns the amount of words.
	public static int getWordCount(int[] countInfo)
	{
		return countInfo[1]; 
	}
	
	// Based on the countLineWordChar method, returns the amount of chars.
	public static int getCharCount(int[] countInfo)
	{
		return countInfo[2]; 
	}
I'm not familiar with the StreamTokenizer. Usually I just use a StringTokenizer. You might watch out that StreamTokenizer parses numbers by default--it doesn't just break up the file by whitespace.

You might have more luck altering your countCharacters or countWords methods than altering your countLines method. If you update countWords, then you just need to increment the line count by 1 every time you read another line, and increase the character count by the length of that line (perhaps plus 1, depending on what it is you would like to count).
 
  • #11
Well StringTokenizers aren't very popular this days

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.

Well I/O is in principles very simple. You either want to read some data or write some data and the data is generally either in "binary" or as "text". I didn't understand that for some time, since hey a text file is a binary file at least I tough soo but technically that is not correct e.g. supose you want to write number 123 onto a file, now if you do it the binary way then the output would be 1111011 or in HEX that is 7B - the value of 123, but if you would write as text 123 to a text file then the output would be 001100010011001000110011, that is 00110001 represents the character '1' 00110010 is char '2' etc. The numbers may not be totally correct but the principles are. That is why you have Writers/Readers for text stuff and Input/Output Streams for binary data.

Try it out:

Code:
	try {
			PrintWriter pw = new PrintWriter(new File("C:/Writer.txt"));
			pw.print(123);
			pw.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {

		}

		try {
			OutputStream is = new FileOutputStream("C:/InputStream.txt");
			is.write(123);
			is.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

If you have time open each file with a Hex editor, you will see that they are different, the text file has 31 32 33 for hex that is 001100010011001000110011 but the binary one has only 7B - 01111011

Readers and InputStream work similar only that you are reading and not writing text or binary sequence.

When using streams in Java it is VERY IMPORTANT that you CLOSE the stream after you have finished with whatever.

Now for your task, you could use directly the FileReader but if you look at the methods of the FileReader they aren't very friendly, just just have the read() method, soo if something doesn't look very friendly in Java it probably has a convenience class/wrapper whatever somewhere, how do you find a convenience class? JavaDocs, Web sites, Java Books, Forums, People, experience.

For working with I/O I find Scanner class the most useful.

Suppose I you want to read an int from the Console

Code:
Scanner consoleInput = new Scanner(System.in);
consoleInput.readInt();

For file

Code:
Scanner fileInput = new Scanner(new File(filename));

while(fileInput.hasNextLine()){

String line = fileInput.nextLine();

// ... do work on the line

}

fileInput.close(); // just to be sure.

I would suggest that you get a good book on programming. In my opinion Big Java is a great book to start learning Java
http://www.horstmann.com/bigjava.html but only if you can find it in the library since the price is not accpetable but there are many other books and tutorials.
 
  • #12
@Haki

Backed on your's and Orthodontist, I understand the follwoing.

In I/O everything is broken up into 2 parts. Reading/Input or Writing/Output. So an example of Reading/Input would be like reading a file on a specific location such as "C:\ReadMe.txt". Then we have Writing/Output when we want to create a new file/append it and write on it. For example, We read the C:\ReadMe.txt file and then write teh same content of it to C:\WriteOnMe.txt.

I hope I got that write so far. We let me try to explain my understand of In/Out Streams and Readers/Writer. In the picture I put below, the Readers/Writers are in red, and In/Out Streams are in blue. I am guessing that we would use the blue stuff when we want to read/write using binary , raw bytes. If we want to use characters to read/writer, we use the red stuff.

But according to my understand, the assignment that my teacher gave me contradicts. Teacher told me

(e) Make a backup copy of the file. To be as general as possible you should treat the file as a binary I/O task. Use the DataInputStream and DataOutputStream classes and the readByte and writeByte methods in your solution.

The "file" he is talking about is a ".txt". So we when we make the copy of the file, we are going to read everything in raw bytes and then writer everything raw bytes. So instead of useing characters, we are using binrary system. But why, if we are writing in streams/binary/bytes, am I able to read the backup copy of the file I made. Why do I see "words/charaters" and not 01010100101. I thought I used binrary instead of charaters. So if I wrote in binary, why do I see it?

io-hierarchy.gif
 
  • #13
a text file consist of a series of characters, characters can be read as binary stream - characters, that is why you can use binary stream to read a text file. But normally you would want to use writers/readers for text stuff they are more suited for that kind of job.
 
  • #14
haki said:
a text file consist of a series of characters, characters can be read as binary stream - characters, that is why you can use binary stream to read a text file. But normally you would want to use writers/readers for text stuff they are more suited for that kind of job.

So I would use STREAM to copy a file for example like a music file. But I would use Reader/WRiter to copy text file?
 

FAQ: Should I Use Streams or Readers/Writers to Copy a Text File?

1. What is Java and why is it important in the field of computer science?

Java is a high-level, object-oriented programming language that is commonly used for developing web applications, mobile applications, and enterprise software. It is important in computer science because it is platform-independent, meaning it can run on any operating system, and it has a large and active community that continuously updates and improves the language.

2. What are the key features of Java that make it popular among developers?

Some key features of Java include its object-oriented nature, which allows for code reusability and easier maintenance; its automatic memory management, which reduces the risk of memory leaks and makes coding less error-prone; and its extensive library of pre-written code, making it easier and faster to develop complex applications.

3. How does someone gain experience in Java?

One can gain experience in Java by taking courses or tutorials, practicing coding exercises and challenges, and working on projects that involve Java. It is also helpful to read code written by experienced Java developers and collaborate with others in the Java community.

4. What are some common challenges that developers face when working with Java?

Some common challenges include learning the syntax and structure of the language, dealing with compatibility issues when using different versions of Java, and understanding the nuances of object-oriented programming. Additionally, debugging and troubleshooting can be challenging, as well as staying updated with the constantly evolving language.

5. What are some career opportunities for someone with experience in Java?

Having experience in Java opens up a wide range of career opportunities, such as software development, web development, mobile app development, system administration, database management, and more. Many large companies and organizations use Java for their software and applications, making it a valuable skill in the job market.

Similar threads

Replies
2
Views
1K
Replies
1
Views
1K
Replies
19
Views
2K
Replies
6
Views
2K
Replies
3
Views
2K
Replies
5
Views
2K
Replies
1
Views
2K
Replies
4
Views
17K
Back
Top