jvm throwing NoSuchElementException when using Scanner - java

I'm facing a problem that i really don't understand.
I designed my program to read info from files and then generate reports about it.
At the first time, I open all the files that I need:
clientesarq = new File(args[1]);
fornecedoresarq = new File(args[3]);
produtosarq = new File(args[5]);
then I use a java.util.Scanner to loop through them:
leitor = new Scanner(clientesarq);
leitor.nextLine();
/* leitura e armazenamento dos clientes em mapa */
while(leitor.hasNextLine()) {
Cliente c = pd.novoCliente(leitor);
clientes.addCliente(c);
}
leitor = new Scanner(fornecedoresarq);
leitor.nextLine();
/* leitura e arazenaento dos fornecedores em mapa */
while(leitor.hasNextLine()) {
Fornecedor f = pd.novoFornecedor(leitor);
fornecedores.addFornecedor(f);
}
when my program reaches this part of the code, the JVM throws to me NoSuchElementException.
leitor = new Scanner(produtosarq);
leitor.nextLine(); /* EXCEPTION HERE */
/* leitura e armazenamento dos produtos em mapa */
while(leitor.hasNextLine()) {
Produto p = pd.novoProduto(leitor);
produtos.addProduto(p);
}
I really want to know why the hell I am getting this excpetion, as you can see, the code is exactly the same as the other ones. Any?
You can get all needed files here: https://www.dropbox.com/sh/c48roudfwuj7qzu/AAAMn_OFGXJFHEjVJyZ7piCPa

Use UTF-8 character set to read from file which is able to represent every character in Unicode Format.
Here it will convert Bytes from the file into characters using the specified charset(Here UTF-8) and will make it readable for Scanner I guess.
Scanner input = new Scanner(new File("filename"),"UTF-8");

Specifying the charset did not fix the issue for me. This post is comment-like as I have not fully discovered the issue, but I am making an attempt at explaining the why portion of the question with what I have found thus far.
I found another post with the same problem as a secondary resource. In both cases, the first line of the files ends with ASCII character 13 carriage return which I would have thought should be picked up by the Scanner as a line separator. As a sanity check, I performed a BufferedReader readLine() and it works fine. Digging deeper, I cloned the source of Scanner and wound up on readInput line 849 : n = source.read(buf);.
After determining the type of source was sun.nio.cs.StreamDecoder, I cloned the class and investigated readImpl. In both cases, line 324 int n = readBytes(); reads the entire file into the buffer hitting the continue and coming back around to line 316 CoderResult cr = decoder.decode(bb, cb, eof); At this point cr is wrapping a MalformedInputException which gets consumed by Scanner catch (IOException ioe).
Since I was able to reproduce this issue in my cloned source, I printed the stacktrace:
java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:281)
at javaapplication1.StreamDecoder.implRead(StreamDecoder.java:349)
at javaapplication1.StreamDecoder.read(StreamDecoder.java:188)
at java.io.Reader.read(Reader.java:100)
at javaapplication1.MyScanner.readInput(MyScanner.java:844)
at javaapplication1.MyScanner.findWithinHorizon(MyScanner.java:1789)
at javaapplication1.MyScanner.nextLine(MyScanner.java:1629)
The decoder at runtime is sun.nio.cs.UTF_8. I've stopped digging at this point as it is way into the AM hours, I may edit in further findings.
The main question now is why the final single character of input kills the decoder.

Just a guess but maybe the file you are trying to read doesnt have any information. Always check if it has a next line before getting that next line.
if(scanner.hasNextLine()){
String line = scanner.nextLine();
}

Related

Problem with input from user saved to file by RandomAccessFile methods

I've got a problem with input from user. I need to save input from user into binary file and when I read it and show it on the screen it isn't working properly. I dont want to put few hundreds of lines, so I will try to dexcribe it in more compact form. And encoding in NetBeans in properties of project is "UTF-8"
I got input from user, in NetBeans console or cmd console. Then I save it to object made up of strings, then add it to ArrayList<Ksiazka> where Ksiazka is my class (basically a book's properties). Then I save whole ArrayList object to file baza.bin. I do it by looping through whole list of objects of class Ksiazka, taking each String one by one and saving it into file baza.bin using method writeUTF(oneOfStrings). When I try to read file baza.bin I see question marks instead of special characters (ą, ć, ę, ł, ń, ó, ś, ź). I think there is a problem in difference in encoding of file and input data, but to be honest I don't have any idea ho to solve that.
Those are attributes of my class Ksiazka:
private String id;
private String tytul;
private String autor;
private String rok;
private String wydawnictwo;
private String gatunek;
private String opis;
private String ktoWypozyczyl;
private String kiedyWypozyczona;
private String kiedyDoOddania;
This is method for reading data from user:
static String podajDana(String[] tab, int coPokazac){
System.out.print(tab[coPokazac]);
boolean podawajDalej = true;
String linia = "";
Scanner klawiatura = new Scanner(System.in, "utf-8");
do{
try {
podawajDalej = false;
linia = klawiatura.nextLine();
}
catch(NoSuchElementException e){
System.err.println("Wystąpił błąd w czasie podawania wartości!"
+ " Spróbuj jeszcze raz!");
}
catch(IllegalStateException e){
System.err.println("Wewnętrzny błąd programu typu 2! Zgłoś to jak najszybciej"
+ " razem z tą wiadomością");
}
}while(podawajDalej);
return linia;
}
String[] tab is just array of strings I want to be able to show on the screen, each set (array) has its own function, int coPokazac is number of line from an array I want to show.
and this one saves all data from ArrayList<Ksiazka> to file baza.bin:
static void zapiszZmiany(ArrayList<Ksiazka> bazaKsiazek){
try{
RandomAccessFile plik = new RandomAccessFile("baza.bin","rw");
for(int i = 0; i < bazaKsiazek.size(); i++){
plik.writeUTF(bazaKsiazek.get(i).zwrocId());
plik.writeUTF(bazaKsiazek.get(i).zwrocTytul());
plik.writeUTF(bazaKsiazek.get(i).zwrocAutor());
plik.writeUTF(bazaKsiazek.get(i).zwrocRok());
plik.writeUTF(bazaKsiazek.get(i).zwrocWydawnictwo());
plik.writeUTF(bazaKsiazek.get(i).zwrocGatunek());
plik.writeUTF(bazaKsiazek.get(i).zwrocOpis());
plik.writeUTF(bazaKsiazek.get(i).zwrocKtoWypozyczyl());
plik.writeUTF(bazaKsiazek.get(i).zwrocKiedyWypozyczona());
plik.writeUTF(bazaKsiazek.get(i).zwrocKiedyDoOddania());
}
plik.close();
}
catch (FileNotFoundException ex){
System.err.println("Nie znaleziono pliku z bazą książek!");
}
catch (IOException ex){
System.err.println("Błąd zapisu bądź odczytu pliku!");
}
}
I think that there is a problem in one of those two methods (either I do something wrong while reading it or something wrong when it is saving data to file using writeUTF()) but even tho I tried few things to solve it, none of them worked.
After quick talk with lecturer I got information that I can use at most JDK 8.
You are using different techniques for reading and writing, and they are not compatible.
Despite the name, the writeUTF method of RandomAccessFile does not write a UTF-8 string. From the documentation:
Writes a string to the file using modified UTF-8 encoding in a machine-independent manner.
First, two bytes are written to the file, starting at the current file pointer, as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for each character.
writeUTF will write a two-byte length, then write the string as UTF-8, except that '\u0000' characters are written as two UTF-8 bytes and supplementary characters are written as two UTF-8 encoded surrogates, rather than single UTF-8 codepoint sequences.
On the other hand, you are trying to read that data using new Scanner(System.in, "utf-8") and klawiatura.nextLine();. This approach is not compatible because:
The text was not written as a true UTF-8 sequence.
Before the text was written, two bytes indicating its numeric length were written. They are not readable text.
writeUTF does not write a newline. It does not write any terminating sequence at all, in fact.
The best solution is to remove all usage of RandomAccessFile and replace it with a Writer:
Writer plik = new FileWriter(new File("baza.bin"), StandardCharsets.UTF_8);
for (int i = 0; i < bazaKsiazek.size(); i++) {
plik.write(bazaKsiazek.get(i).zwrocId());
plik.write('\n');
plik.write(bazaKsiazek.get(i).zwrocTytul());
plik.write('\n');
// ...

Check whether data can be represented in a specified encoding

I'm writing a Java program that saves data to UTF8 text files. However, I'd also like to provide the option to save to IBM437 for compatibility with an old program that uses the same sort of data files.
How can I check to see if the data the user is trying to save isn't representable in IBM437? At the moment the file saves without complaining but results in unusual characters being replaced with question marks.
I'd prefer it if I could show a warning to the user that the data they are saving isn't supported in IBM437. The user could then have the option of manually replacing characters with the nearest ASCII equivalent.
Current code for saving is:
String encoding = "UTF-8";
if (forceLegacySupport)
{
// Force character encoding to IBM437
encoding = "IBM437";
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(saveFile.getAbsoluteFile()), encoding));
IOController.writeFileToDisk(bw);
bw.close();
As mentioned by JB Nizet in comments you can use charset encoder
and for creating text/String as UTF-8
just a suggestion from my end:
public static char[] cookie = "HEADER_COOKIE".toCharArray();
byte[] cookieInBytes = new byte[COOKIE_SIZE];
for(int i=0;i<cookie.length;i++)
{
if(i < cookie.length)
cookieInBytes[i] = (byte)cookie[i];
}
String headerStr = new String(cookieInBytes,StandardCharsets.UTF_8);

How to get rid of "Rogue Chars" in an .txt encoded under UTF-8

My program is reading from a .txt encoded with UTF-8. The reason why I'm using UTF-8 is to handle the characters åäö. The problem I come across is when the lines are read is that there seems to be some "rogue" characters sneaking in to the string which causes problems when I'm trying to store those lines into variables. Here's the code:
public void Läsochlista()
{
String Content = "";
String[] Argument = new String[50];
int index = 0;
Log.d("steg1", "steg1");
try{
InputStream inputstream = openFileInput("text.txt");
if(inputstream != null)
{
Log.d("steg2", "steg2");
//InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
//BufferedReader bufferreader = new BufferedReader(inputstreamreader);
BufferedReader in = new BufferedReader(new InputStreamReader(inputstream, "UTF-8"));
String reciveString = "";
StringBuilder stringbuilder = new StringBuilder();
while ((reciveString = in.readLine()) != null)
{
Argument[index] = reciveString;
index++;
if(index == 6)
{
Log.d(Argument[0], String.valueOf((Argument[0].length())));
AllaPlatser.add(new Platser(Float.parseFloat(Argument[0]), Float.parseFloat(Argument[1]), Integer.parseInt(Argument[2]), Argument[3], Argument[4], Integer.parseInt(Argument[5])));
Log.d("En ny plats skapades", Argument[3]);
Arrays.fill(Argument, null);
index = 0;
}
}
inputstream.close();
Content = stringbuilder.toString();
}
}
catch (FileNotFoundException e){
Log.e("Filen", " Hittades inte");
} catch (IOException e){
Log.e("Filen", " Ej läsbar");
}
}
Now, I'm getting the error
Invalid float: "61.193521"
where the line only contains the chars "61.193521". When i print out the length of the string as read within the program, the output shows "10" which is one more character than the string is supposed to contain. The question; How do i get rid of those invisible "Rouge" chars? and why are they there in the first place?
When you save a file as "UTF-8", your editor may be writing a byte-order mark (BOM) at the beginning of the file.
See if there's an option in your editor to save UTF-8 without the BOM.
Apparently the BOM is just a pain in the butt: What's different between UTF-8 and UTF-8 without BOM?
I know you want to be able to have extended characters in your data; however, you may want to pick a different encoding like Latin-1 (ISO 8859-1).
Or you can just read & discard the first three bytes from the input stream before you wrap it with the reader.
Unfortunately you have not provided the sample text file so testing with your code exactly is not possible and here is the theoretical answer based on guess, what could have been the reasons:
Looks like it is BOM related issue and you may have to treat this. Some related detail is given here: http://www.rgagnon.com/javadetails/java-handle-utf8-file-with-bom.html
And some information here: What is XML BOM and how do I detect it?
Basically there are various situation:
In one of the situation we face issues when we don't read and write using correct encoding.
In another situation we use an editor or reader which doesn't support UTF-8
Third is when we are using correct encoding for reading and writing, we are not facing issue in a text editor but facing issue in some other application or program. I think your issues is related to third case.
In third situation we may have to remove the BOM using a program or deal with it according to our context.
Here is some solution I guess you may find interesting:
UTF-8 file reading: the first character issue
You can use code given in this threads answer or use apache commons to deal with it:
Byte order mark screws up file reading in Java

Caught between "Line is longer than 80 characters" and "File contains tab characters"

I have installed the latest version of Checkstyle in my Eclipse.
The problem is this: If I set the Tab policy to "Tabs" I get all the "File contains tab characters" errors. If I set the Tab policy in Formatter to "Spaces only" I get rid of the "File contains tab characters" checkstyle errors BUT I get lots of "Line is longer than 80 characters errors", even when they make no sense, in my opinion. For example:
FulltimeEmployee a = new FulltimeEmployee(
parsedLine[READ_LINE_FIRST_PARAMETER],
parsedLine[READ_LINE_SECOND_PARAMETER],
Integer.decode(parsedLine[2].trim()));
Now, all those line have actually about 40 "useful" characters. The rest come from indentation. I don't see how I could further break down those lines to conform to the 80 rule. Should I set Indentation size to less than 4 spaces?
I thought about simplifying my code to not be so deeply indented, but I don't see how. See below for more code listing, perhaps you can suggest how I can reduce indentation. Even if that is the case here, my original problem still stands. The first indentation in front of the method is from the class.
public void populateList() {
String[] parsedLine = new String[NUMBER_OF_PARAMETERS];
try {
FileInputStream fstream = new FileInputStream(Company.fileName);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine;
while ((readLine = br.readLine()) != null) {
parsedLine = readLine.split(", ");
if (parsedLine.length != NUMBER_OF_PARAMETERS) {
System.out.println("Format error");
} else {
switch (parsedLine[READ_LINE_THIRD_PARAMETER]) {
case "full-time":
FulltimeEmployee a = new FulltimeEmployee(
parsedLine[READ_LINE_FIRST_PARAMETER],
parsedLine[READ_LINE_SECOND_PARAMETER],
Integer.decode(parsedLine[2].trim()));
this.employeeList.add(a);
//more code here
Any suggestions? I have thought long about this and searched quite a bit, but am at a loss.
use limitation - 120 symbols in line. Checkstyle should help your team to work in more uniform way, but to make you suffer, adjust it to your needs!
Now we have wide screens and this rule become outdated.
To make Line length be even more relaxed you can try our extension to checkstyle, search LineLengthExtendedCheck.

JAVA NullpointerException FileInputStream(File file)

I have a problem not to solve by myself.
I'm a biginner in JAVA.
I don't know solution about this problem. But I think that I know when this problem occurs.
So, I aleady have solution about this problem. But I want another solution because my solution has another problem too. I have to reduce the process time.
String intDir="C:\\RNE_IN";
while(true) {
File interfaceDirectory = new File(intDir);
String[] arrayfiles = interfaceDirectory.list(new FBMFileFilter());
for(String f : arrayfiles){
String filename = String.format("%1$s%2$s%3$s", intDir,File.separator,f);
File file = new File(filename);
FileInputStream stream = null;
System.out.println(file.canExecute()); // true
System.out.println(file.canRead()); // true
System.out.println(file.exists()); // true
System.out.println(file.isFile()); // true
System.out.println(file.length()); // call full bytes of file
// I can control NPE with this Thread sleep Time.
Thread.sleep(1);
// It occurs when Stream is constructed in the below.
stream = new FileInputStream(file);
FBMDeviceOnlyParser onlyparser = new FBMDeviceOnlyParser();
onlyparser.ParseDeviceNameOnly(stream);
String onlydevice = onlyparser.getDeviceName();
String onlystepseq = onlyparser.getStepSeq();
}
}
In above snippet, I think file has no problem.
file state is always true and file.length is full byte regardless Exception.
But, while infinite Loop, If I copy & paste from another Directory to the intDir , "NullPointerException" occurs.
When Thread.sleep(time) is over 1000ms, NPE doesn't occur.
I want to delete "Thread.sleep()" code because of process time.
If there are files in the intDir aleady before program start, Program has No problem (it doesn't occur NPE)
I want to check file or FileInputStream state not to occur NPE.
Thank you for your concern.
Your question is hard to understand, but I can tell you for a fact that it is impossible to get:
java.lang.NullPointerException at Apeiron.MainEntry.main(MainEntry.java:179) Exception in thread "main"
java.lang.NullPointerException at Apeiron.MainEntry.main(MainEntry.java:260)
if line 179 is this line:
stream = new FileInputStream(file);
One of the following must be:
you have given us an incomplete stack trace, or
you've told us the incorrect location of the exception, or
you are not actually executing that code at all; e.g. you've not rebuilt the code properly after changing it.
You probably run out of file handles sooner or later. Close the FileInputstream when you are finished with it.
Besides that, explain what you really want to do with your code (instead of driving CPU usage to the top).
How about this:
String intDir="C:\\RNE_IN";
File interfaceDirectory = new File(intDir);
while(true) {
for(File file : interfaceDirectory.listFiles(new FBMFileFilter())) {
System.out.println(file.canExecute()); // true
System.out.println(file.canRead()); // true
System.out.println(file.exists()); // true
System.out.println(file.isFile()); // true
System.out.println(file.length()); // call full bytes of file
final FileInputStream stream = new FileInputStream(file);
try {
FBMDeviceOnlyParser onlyparser = new FBMDeviceOnlyParser();
onlyparser.ParseDeviceNameOnly(stream);
String onlydevice = onlyparser.getDeviceName();
String onlystepseq = onlyparser.getStepSeq();
} finally {
stream.close();
}
}
}
I did a couple of things --
1. got rid of unnecessary file name generation
2. put a try finally to release file handle resources
BTW, my guess is that your sleep allowed finalizers to run.

Categories

Resources