I was searching on the internet and came across this code to read files from a file and convert it into a string. But I don't understand how in.read(arr) is reading all the contents of a file at once.
import java.util.Scanner;
import java.io.*;
class Main{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
BufferedReader in = new BufferedReader(new FileReader(file));
int c;
char arr[] = new char[(int)file.length()];
in.read(arr);
String res = new String(arr);
System.out.println(res);
}
catch(Exception e){}
}
}
In contemporary Java code you would use Files.readString for this purpose. It was introduced with Java 11, and it specifically reads an entire text file into a String.
What happens in the code you ask about is a common thing with read(someArray) methods: they read up to a number of conditions, something like
The specified number of characters have been read,
The read method of the underlying stream returns -1, indicating end-of-file, or
The ready method of the underlying stream returns false, indicating that further input requests would block.
here you use the first and second conditions, and hope that the third one will not kick in, so reading from a local file won't cause "blocking" at an arbitrary file position.
File.length tells you the size of the file in bytes. There can't be more characters in a file than its size in bytes, that's why file.length is a good upper estimate for the number of characters you would need. However as there are encodings which can result a single character stored as multiple bytes (such as UTF-8), you should actually use the return value of that read() call which tells you the number of characters read, and then pass it to the String constructor:
char arr[] = new char[(int)file.length()];
int count = in.read(arr);
String res = new String(arr, 0, count);
Actual variants of your code:
with File.toPath() if you like
import java.util.Scanner;
import java.io.File;
import java.nio.file.Files; // "Files" is needed of course
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
String res = Files.readString(file.toPath()); // many lines disappeared
System.out.println(res);
}
catch (Exception e) {}
}
}
with java.nio classes and interfaces:
import java.util.Scanner;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
Path path = Paths.get(s); // "File file" became "Path path"
String res = Files.readString(path); // many lines disappeared again
System.out.println(res);
}
catch (Exception e) {}
}
}
It's up to a bit of taste and what you have already. If you have a File object anyway (like you need its size for some another purpose, or you get it from GUI code for example - in many cases that's going to be a File), use its toPath(). If you have a String, a single Paths.get() is less typing.
The object 'in' has the information related to file.
'arr' is the array whose length is equal to the length of file contents.
Then 'in' is read upto that length of file
Related
I'm having trouble properly getting one line of text at a time from a file onto a queue without taking the whole file into the queue. For example, I'd like only Write a program that reads a Java source file as an argument and produces an index of all identifiers in the file. For each identifier, print all lines in which it occurs. For simplicity, we will consider each string consisting only of letters, numbers, and underscores an identifier.
Declare a Scanner in for reading from the source file and call in.useDelimiter("[^A-Za-z0-9_]+") Then each call to next returns an identifier.
public class Main { to get added to the queue but instead the whole file text is put into the queue instead of a line at a time. Sorry if my question is unclear
// Write a program that reads a Java source file as an argument and produces an index of all
// identifiers in the file. For each identifier, print all lines in which it occurs. For simplicity,
// we will consider each string consisting only of letters, numbers, and underscores an identifier.
// Declare a Scanner in for reading from the source file and call in.useDelimiter("[^A-Za-z0-9_]+").
// Then each call to next returns an identifier.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class E_15 {
public static void main(String[] args) throws FileNotFoundException
{
// get scanner input from file
Scanner fileInput = new Scanner(new File ("C:/Users/ramir/IdeaProjects/PA_7/src/Main.java"));
Queue<String> test = new LinkedList<String>();
ArrayList<String> phrase = new ArrayList<String>();
/*
List<String> result = new ArrayList<String>();
Scanner s = new Scanner(is);
s.useDelimiter(delimiter);
*/
// Iterates till end of file
while (fileInput.hasNextLine())
{
// Here is the issue. Data will end up
// containing the whole file instead of only that line
String data = fileInput.nextLine();
Scanner in = new Scanner(data);
in.useDelimiter("[^A-Za-z0-9_]+");
// I believe around here or before is the issue that I'm having.
// It adds all the file instead of only that line
// Also trying to figure out how to display each line that it's displayed on
// What the first one should look like for example
// 0: public occurs in:
// public class Main {
// public static void main(String[] args) {
//System.out.println(data);
test.add(data);
while(in.hasNext())
{
// Getting each phrase/word into ArrayList
String token = in.next();
phrase.add(token);
}
in.close();
}
int index = 0;
// This part works fine
for(String num : phrase)
{
// printing the key
System.out.println(index + ": " + num + " occurs in:");
// printing the values
// This to print out what
for(String line : test)
{
System.out.println(line);
}
System.out.println();
++index;
}
}
}
// Just java class get file front
// This is fine
public class Main {
public static void main(String[] args) {
int a_1 = 100;
System.out.println(a_1);``
}
}
I'd like it to only show System.out.println(a_1) because the line that's it's on See This
. I'm also have trouble printing it in all the lines that occur.
import java.io.*;
import java.util.Scanner;
public class ReadLineByLineExample2
{
public static void main(String args[])
{
try
{
//the file to be opened for reading
FileInputStream fis=new FileInputStream("Demo.txt");
Scanner sc=new Scanner(fis); //file to be scanned
//returns true if there is another line to read
while(sc.hasNextLine())
{
System.out.println(sc.nextLine()); //returns the line that was skipped
}
sc.close(); //closes the scanner
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Try studying the above code. I hope it will help. Otherwise, you might need to open this link for more detail.
im tasked with written two java programs. One program creates a file called 'userinput.txt', then writes everything the user inputs into the file. Once done a new file is created called 'Checksum.txt' and this file will write down the checksum for the 'userinput.txt' file after reading whats inside of it.
The 2nd program just reads the same 'userinput.txt' file and then generates a checksum and prints it onto the console (i also have to get the program to read the other checksum.txt file and display it int the console to compare the two but i havent gotten around to that yet).
Iv written the program for these two but my problem is they are both different checksum even though they are reading the same file. Im using Adler32 but CRC32 also gives me two different checksums (the one on console is always different to the one stored in checksum.txt) and im not sure whats causing it frankly :/
Here is the code that takes userinput and generates the checksum file:
package attemp2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
public class main {
public static void main(String[] args) throws IOException {
System.out.println("All inputs will be recorded into a sigle file. Enter 'x' when done. A checksum File will aslo be created at the end");
FileWriter fw = new FileWriter("d:/input.txt", false); // clears previous entry in file.
while (true) {
Scanner input = new Scanner(System.in); //get user input
String ch = input.nextLine(); //stores user input
System.out.println(ch); //prints out what user just inputed
if (ch.equals("x")) { //stops running if 'x' is entered
break;
}
BufferedWriter writer = new BufferedWriter(new FileWriter("d:/input.txt", true));
writer.write(ch);
writer.newLine(); // Add new line
writer.close();
}
try {
FileReader reader = new FileReader("d:/input.txt");
BufferedReader br = new BufferedReader(reader);
// read line by line String line;
String read = "";
String line;
while ((line = br.readLine()) != null) {
read = read + line;
//prints out text in file currently
System.out.println(line);
}
//checksum.txt generation
byte buffer[] = read.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
byte readBuffer[] = new byte[buffer.length];
cis.read(readBuffer);
FileOutputStream out = new FileOutputStream("d://checksum.txt");
BufferedWriter wrt = new BufferedWriter(new FileWriter("d:/checksum.txt", false));
wrt.write(Long.toString(cis.getChecksum().getValue()));
wrt.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
The code that reads the file and generates a checksum in console:
package check;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.zip.Adler32;
public class CheckSum {
private Adler32 checksum;
private String filepath;
InputStream inputStream;
public CheckSum(String filepath) throws FileNotFoundException{
this.filepath = filepath;
checksum = new Adler32();
inputStream = new FileInputStream(filepath);
}
public long generateChecksum() throws IOException{
int c;
while((c = inputStream.read())!=-1){
checksum.update(c);
}
return checksum.getValue();
}
public void read() throws IOException{
File file = new File(filepath);
BufferedReader br = new BufferedReader(new FileReader(file));
String st;
while ((st = br.readLine()) != null) {
System.out.println(st);
}
}
public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
String filepath = "d:/input.txt";
CheckSum checksum = new CheckSum(filepath);
checksum.read();
System.out.println("For the file: "+filepath);
System.out.println("The checksum generated is: "+checksum.generateChecksum());
}
}
Please learn how to use a debugger, see What is a debugger and how can it help me diagnose problems?.
That being said, you have some problems with your code. First you are calculating the checksum on an empty array. When you write:
byte readBuffer[] = new byte[buffer.length];
cis.read(readBuffer);
you are reading an empty array of the size of the buffer array. You don't need to create a new array. In fact, you should read the buffer array you already have, since there is your content. In this case you just write:
cis.read(buffer);
The next problem is that you are using readers and writers, which are used for text/string files, but checksum/hash algorithm usually works on byte level. This can result in several errors like encoding (ASCII, UTF-8, etc. stuff) and line-termination issues (\n vs. \r\n vs. \r).
However, in this case you are working with readLine(). This method does not return the line-termination at the end, see the documentation of readLine():
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
So, what you are reading from the file is not the same what is actually in the file. But your CheckSum class reads every byte in the saved file (as it should). Assume you enter only the string "abc". Your first calculation will be run on the 3 bytes long array with the values:
[97,98,99]
The line-termination is ignored by the readLine() method, but it is still present in the file. When you check the checksum with the second program, the InputStream you are using will see the following bytes:
[97,98,99,10]
(The bytes at the end depends on the OS you are using)
As you see you run the checksum on different byte arrays, resulting in different checksum values. So, make sure you are running the checksum checks on the same byte array content (or InputStream content) to get the same checksum in both applications.
Currently, I'm attempting (and failing) to read from a file in the context of this homework assignment. The program is supposed to return a list of the number of each word in a separate file when run, yet it returns nothing but a blank screen. I am making use of the File Reader object in Java, and using a scanner class to read individual words from that file reader.
I have already tried buffered reader in a similar instance. There is no file not found error, so that can't be it.
import java.util.*;
import java.io.*;
public class Driver {
public static void main(String[] args) {
FileReader inputStream = null;
try {
inputStream = new FileReader("C:\\Users\\[my username]\\Documents\\lorem ipsum.txt");
System.out.println("Testing.");
boolean placeholder = false;
WordBag textfile = new WordBag(2000);
Scanner scan = new Scanner(inputStream);
while (scan.hasNext()) {
Word temp = new Word(scan.next());
placeholder = textfile.add(temp);
if (placeholder = false) {
System.out.println("Addition failed.");
}
}
while (!textfile.isEmpty()) {
System.out.println(textfile.remove().toString());
}
}
catch (FileNotFoundException e){
System.out.println("File not found.");
}
}
}
The Word object type has two variables-- One which stores the string, and the second which stores the frequency with which the word appears in the file.
The WordBag object is essentially an array of these word objects, with some particular methods.
The expected output should be a list of the various words within the file. However, it is printing nothing whatsoever on the screen.
Edit: It is printing only "Testing." My apologies, I didn't describe the output accurately.
I'm trying to write some text to a file. I have a while loop that is supposed to just take some text and write the exact same text back to the file.
I discovered that the while loop is never entered because Scanner thinks there's no more text to read. But there is.
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class WriteToFile {
public static void main(String[] args) throws FileNotFoundException {
String whatToWrite = "";
File theFile = new File("C:\\test.txt");
Scanner readinput = new Scanner(theFile);
PrintWriter output = new PrintWriter(theFile);
while (readinput.hasNext()) { //why is this false initially?
String whatToRead = readinput.next();
whatToWrite = whatToRead;
output.print(whatToWrite);
}
readinput.close();
output.close();
}
}
The text file just contains random words. Dog, cat, etc.
When I run the code, text.txt becomes empty.
There was a similar question: https://stackoverflow.com/questions/8495850/scanner-hasnext-returns-false which pointed to encoding issues. I use Windows 7 and U.S. language. Can I find out how the text file is encoded somehow?
Update:
Indeed, as Ph.Voronov commented, the PrintWriter line erases the file contents! user2115021 is right, if you use PrintWriter you should not work on one file. Unfortunately, for the assignment I had to solve, I had to work with a single file. Here's what I did:
import java.util.ArrayList;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class WriteToFile {
public static void main(String[] args) throws FileNotFoundException {
ArrayList<String> theWords = new ArrayList<String>();
File theFile = new File("C:\\test.txt");
Scanner readinput = new Scanner(theFile);
while (readinput.hasNext()) {
theWords.add(readinput.next());
}
readinput.close();
PrintWriter output = new PrintWriter(theFile); //we already got all of
//the file content, so it's safe to erase it now
for (int a = 0; a < theWords.size(); a++) {
output.print(theWords.get(a));
if (a != theWords.size() - 1) {
output.print(" ");
}
}
output.close();
}
}
PrintWriter output = new PrintWriter(theFile);
It erases your file.
You are trying to read the file using SCANNER and writing to another file using PRINTWRITER,but both are working on same file.PRINTWRITER clear the content of the file to write the content.Both the class need to work on different file.
I'm reading a file into an array and trying to take out the numbers and put them as a double in an array of their own. And apparently my middle name must be "Error". From what I can tell the code is ok....at least theres nothing jumping out at me. Here it is in all it's glory.
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.lang.Object.*;
public class ReadFromFile {
public static void main (String[] args){
File file = new File("vector10.txt");
FileInputStream fis = null;
BufferedInputStream bis = null;
DataInputStream dis = null;
StringBuffer sb = new StringBuffer();
String string = new String();
try{
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
while((string=dis.readLine()) != null){
sb.append(string+"\n");
}
fis.close();
bis.close();
dis.close();
System.out.println(sb);
String newString = sb.toString();
System.out.println(newString);
String[] doubles = newString.split(",");
for (int i=0; i<doubles.length; i++){
System.out.println(doubles[i]);
}
Double arrDouble[] = new Double[doubles.length];
int idx = 0;
for(String s : doubles) {
arrDouble[idx++] = Double.parseDouble(s);
}
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
It keeps throwing an error
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Long.parseLong(Long.java:412)
at java.lang.Long.parseLong(Long.java:461)
at ReadFromFile.main(ReadFromFile.java:51)
Programming is not necessarily my strong point and my eyes are starting to bleed looking at the screen.
Any thoughts or tips are gratefully appreciated.
Cheers
If your file is comma separated then it's better to use Scanner
String doubles = "1.25, 1.65, 1.47";
Scanner f = new Scanner(doubles);
f.useLocale(Locale.US); //without this line the program wouldn't work
//on machines with different locales
f.useDelimiter(",\\s*");
while (f.hasNextDouble()) {
System.out.println(f.nextDouble());
}
Maybe you can try using Scanner class?
Scanner sc = new Scanner(new File("vector10.txt"));
ArrayList<Double> lst = new ArrayList<Double>();
while (sc.hasNextDouble()) {
lst.add(new Double(sc.nextDouble()));
}
Your code doesn't seem to be the one actually run, but in your code, you are building a big string of all your numbers, separated by newlines. But then you split it (using String.split) at commas, and there are no commas in that string. So Double.parseDouble gets all the numbers at once.
The error says that you are calling Long.parseLong(), not Double.parseDouble(), as the code you posted says. Perhaps you forgot to recompile?
That could be the whole problem, but if not send a System.out.println(string) of the value you are going to call Double.parseDouble(string) right before so you can see the value it fails on.
Double.parseDouble() like all parse* methods do not react well to characters that they don't expect, and that - unfortunately - includes white space. A few spaces in your string can ruin your whole day.
To solve, first it will be a good idea to split on spaces as well, so something like newString.split("[,\\s]+") would work nicely by splitting and removing any sequence of white-space and/or commas. Then when you try to parse, trim your string - just for safety - something like Double.parseDouble(doubles[i].trim()). For extra safety, check if your trimmed string is not the empty string before parsing - maybe something like if (doubles[i].trim().length() < 1) continue;.
Good luck.