I have a method that stores an int in a .dat file (among other things) later I try to retrieve that in with a different method and it gives an absurd value. For example if I try to store a 1 the other method retrieves 484449. I'm new to Java so if this is somehow normal please explain.
Method that writes int:
public static int fromText (String textRefference, String binaryRefference,
boolean overwrite, String countRefference){
if(!(new File(binaryRefference).exists()))overwrite = true;
BufferedReader input;
ObjectOutputStream output;
ObjectInputStream binaryInput;
ObjectInputStream countStreamI;
ObjectOutputStream countStreamO;
int count = 0;
try{
input = new BufferedReader(new FileReader(textRefference));
String[] data = null;
int oldCount = 0;
if(!overwrite){
countStreamI = new ObjectInputStream(new FileInputStream(countRefference));
binaryInput = new ObjectInputStream(new FileInputStream(binaryRefference));
oldCount = countStreamI.readInt();
data = new String[oldCount];
int i;
for(i = 0;i < oldCount; i++){
data[i] = binaryInput.readUTF();
}
countStreamI.close();
}
countStreamO = new ObjectOutputStream(new FileOutputStream(countRefference));
output = new
ObjectOutputStream(new FileOutputStream(binaryRefference));
String sentinel = input.readLine();
String[] data2 = new String[1500];
while(!sentinel.equalsIgnoreCase("end")){
System.out.println(sentinel + " has been recorded");
data2[count] = sentinel;
sentinel = input.readLine();
count++;
}
count += oldCount;
countStreamO.writeInt(count);
if(!overwrite){
int i;
for(i = 0; i < oldCount;i++){
output.writeUTF(data[i]);
}
}
int i = 0;
for(; i < count + oldCount;i++){
output.writeUTF(data2[i]);
}
output.flush();
countStreamO.flush();
countStreamO.close();
output.close();
input.close();
}
catch(Exception e){
Scanner in = new Scanner(System.in);
e.printStackTrace();
in.nextLine();
System.exit(0);
}
return count;
}'
And the function retrieving it:
public static String[] pullStrings(String file, String countReferrence, boolean print){
String[] data = null;
try{
ObjectInputStream input = new ObjectInputStream(new FileInputStream(file));
int count = input.readInt();
data = new String[count];
int i = 0;
String string;
for(;i < count; i++){
string = input.readUTF();
if(print)System.out.println(string);
data[i] = string;
}
}
catch(Exception e){
Scanner in = new Scanner(System.in);
System.out.println(e.getMessage() + "\n\n");
e.printStackTrace();
System.out.println("\n hit ENTER to exit.");
in.nextLine();
System.exit(0);
}
return data;
}
And the text file:
data!!!
end
This strange number you're getting, 484449, is actually the result of reading four bytes: 00 07 64 61.
Where did those bytes come from? Well, for some reason, you chose to send count to a different file, using countStreamO.writeInt(count);. So when your retrieval code executes input.readInt(), it's expecting to find a count in the same file, but you never wrote it there.
Instead, you sent the count to a different file, then proceeded to write each string to the main data file using output.writeUTF(data[i]) and output.writeUTF(data2[i]).
What does writeUTF actually do? Well, the documentation for ObjectOutputStream.writeUTF doesn't say much about it, except that the method is mandated by the DataOutput interface. The documentation for DataOutput.writeUTF is pretty informative, though:
Writes two bytes of length information to the output stream, followed by the modified UTF-8 representation of every character in the string s.
So you never wrote your count value to the file, but you did send the string "data!!!" to it. And now we know that writeUTF first writes the byte length of that string (after converting it to modified UTF-8) followed by the modified UTF-8 bytes themselves.
In this case, your String consists entirely of ASCII characters, which, when encoded in modified UTF-8 (or real UTF-8, for that matter), take up one byte each, with no encoding required. So the string requires 7 bytes, one for each character.
Meaning, the writeUTF method wrote two bytes for the byte length (00 07) followed by seven bytes for the characters (64 61 74 61 21 21 21).
Which means the first four bytes in the file are 00 07 64 61. You're trying to read them as 32-bit int, so you're getting 0x00076461, or 484449.
Your code is far more complicated than it needs to be. That complexity makes it difficult to see small problems like this one. Also, some documentation would have made it clear what your code should be doing. It looks like you realized by the time you got around to writing the retrieval code that you didn't need a separate file for the count, but you never went back and updated the code that writes the data to accommodate the improvement.
I don't know if your data file needs to adhere to an externally specified format, but if it doesn't, you can easily accomplish your task by doing away with counts entirely, and doing away with readUTF and writeUTF. Instead, you can simply serialize a String array:
String[] allData = new String[data.length + data2.length];
System.arraycopy(data, 0, allData, 0, data.length);
System.arraycopy(data2, 0, allData, data.length, data2.length);
try (ObjectOutputStream out = new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream(binaryReference)))) {
out.write(allData);
}
The length is part of the array object's state, so it is included in the serialized output.
Reading it is even easier:
String[] data;
try (ObjectInputStream in = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(file)))) {
data = (String[]) in.readObject();
}
Related
So I am trying to return a large string array of length 200, but the code I am using only returns 15/ sets the array length to 15 during execution when it has been initiated to reserve 200 spaces as the size of the array may change so I made it big to try and accommodate different sizes.
public static String[] populateArray(String fileName)
{
String [] record = new String [200]; // array length is 200
try
{
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = null;
int counter = 0;
int arrayLength = 0; // using this to check length during execution
while((line = bufferedReader.readLine())!= null && counter < 200)
{
record[counter] = line;
counter +=1;
arrayLength = record[0].length(); // the file contains 20 lines to input here but
only does 15
}
bufferedReader.close();
}
catch (IOException ex)
{
System.out.println("There was an error while trying to access the file");
}
return record;
}
Is the first line of the file 15 characters long? It looks like you're finding the length of that string, instead of the amount of lines read in. Furthermore, you set the arrayLength variable to the same value, in each loop iteration.
If you want to count lines read, I suggest just printing the counter variable.
The code you posted seems to work, reading in all the file's lines (With my test file). I'm guessing, therefore, that your issue was with looking at the wrong variable in order to verify what was read in.
I am trying to make function which will remove diacritic(dont want to use Normalizer on purpose).Function looks like
private static String normalizeCharacter(Character curr) {
String sdiac = "áäčďéěíĺľňóôőöŕšťúůűüýřžÁÄČĎÉĚÍĹĽŇÓÔŐÖŔŠŤÚŮŰÜÝŘŽ";
String bdiac = "aacdeeillnoooorstuuuuyrzAACDEEILLNOOOORSTUUUUYRZ";
char[] s = sdiac.toCharArray();
char[] b = bdiac.toCharArray();
String ret;
for(int i = 0; i < sdiac.length(); i++){
if(curr == s[i])
curr = b[i];
}
ret = curr.toString().toLowerCase();
ret = ret.replace("\n", "").replace("\r","");
return ret;
}
funcion is called like this(every charracter from file is sent to this function)
private static String readFile(String fName) {
File f = new File(fName);
StringBuilder sb = new StringBuilder();
try{
FileInputStream fStream = new FileInputStream(f);
Character curr;
while(fStream.available() > 0){
curr = (char) fStream.read();
sb.append(normalizeCharacter(curr));
System.out.print(normalizeCharacter(curr));
}
}catch(IOException e){
e.printStackTrace();
}
return sb.toString();
}
file text.txt contains this: ľščťžýáíéúäôň and i expect lcstzyaieuaonin return from program but insted of expected string i get this ¾è yaieuaoò. I know that problem is somewhere in encoding but dont know where. Any ideas ?
You are trying to convert bytes into characters.
However, the character ľ is not represented as a single byte. Its unicode representation is U+013E, and its UTF-8 representation is C4 BE. Thus, it is represented by two bytes. The same is true for the other characters.
Suppose the encoding of your file is UTF-8. Then you read the byte value C4, and then you convert it to a char. This will give you the character U+00C4 (Ä), not U+013E. Then you read the BE, and it is converted to the character U+00BE (¾).
So don't confuse bytes and characters. Instead of using the InputStream directly, you should wrap it with a Reader. A Reader is able to read charecters based on the encoding it is created with:
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(f), StandardCharsets.UTF_8
)
);
Now, you'll be able to read characters or even whole lines and the encoding will be done directly.
int readVal;
while ( ( readVal = reader.read() ) != -1 ) {
curr = (char)readVal;
// ... the rest of your code
}
Remember that you are still reading an int if you are going to use read() without parameters.
I'm trying to extract a file from my jar and copying it into the temp directory.
To read the file within the jar, I am using a DataInputStream, to write the file in the temp directory, I am using a DataOutputStream.
The file I am trying to extract has a file size of 310 kilobytes, my copied file only contains 114 bytes after I've called my method (this is also the number of bytes my method prints to the console).
Here is my method:
private static void extractFile(String pathInJar, String fileToCopy) {
File outputFile = new File(System.getProperty("java.io.tmpdir") + "/LDEngine/"+fileToCopy);
boolean couldDirsBeCreated = outputFile.getParentFile().mkdirs();
if(couldDirsBeCreated && !outputFile.exists()) {
int x;
int actualBytesRead = 0;
byte[] tmpByteArray = new byte[4096];
try(
DataOutputStream output = new DataOutputStream(new FileOutputStream(outputFile));
DataInputStream in = new DataInputStream(LibLoader.class.getResourceAsStream("/libs/natives/"+pathInJar))
){
while((x=in.read(tmpByteArray)) != -1) {
output.write(tmpByteArray);
actualBytesRead += x;
}
} catch(Exception e) {
System.err.println("Fatal error: Could not write file!");
System.exit(1);
}
System.out.println(actualBytesRead);
}
}
The file I am trying to copy is a .dll, so it's binary data I'm dealing with.
The question is why is this happening and what am I doing wrong?
This does not explain why your method stops so soon, but you need to take care of it or you will have an even stranger problem with the result data being completely garbled.
From the APi doc of DataInputStream.read():
Reads some number of bytes from the contained input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer.
You need to use that return value and call the write() method that takes and offset and length.
I am getting exception thrown and i think it has to with the ArrayIndexOutOfBounds at the sub string and also do you think the below method would work for getting data passed to my array after parsing
I want this to be read from a txt file like this, on each line:
1
0
1
0
0
1
0
ONE INTEGER PER LINE!!
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()){
data1 = scanner.nextLine();
}
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
This is previous working version but it reads from the console. where it would be : 1010101001
System.out.println("Enter the binary bits");
data1 = in.next();
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
You're reading all the lines and only keeping the last in your data1 variable. That's probably your problem.
You should, instead, handle each value right away while reading the file, and build an ArrayList instead of an array (because you won't know its size beforehand):
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
ArrayList<Byte> covertDataList= new ArrayList<>();
while(scanner.hasNextLine()){
String line = scanner.nextLine(); // the line should be just a number
covertDataList.add(Byte.parseByte(line)); // no substring needed
}
If you want to fail nicely when the file format is wrong, you may surround parseByte with a try/catch block.
About the ArrayList
If you want to use your list as an array, you can just:
use covertDataList.get(i) instead of covertDataArray[i]
use covertDataList.set(i, value); instead of covertDataArray[i] = value;
If you really need an array (I don't see the point here), you can do this:
Byte[] covertDataArray = covertDataList.toArray(new Byte[list.size()]);
I am trying to do telnet to a router with expect kind of implementation.
My code is as follows for the socket communication is as follows,
server = "my-server-ip-domain-here";
socket = new Socket();
socket.connect(new InetSocketAddress(server, 23), 10000);//Will wait for 10 seconds
socket.setKeepAlive(true);
socket.setSoTimeout(10000);
expectBuffer = new StringBuilder();
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(), true);
My send implementation is as follows,
public static void send(String cmd) {
pw.print(cmd + "\r");
pw.flush();
}
My expect implementation is as follows,
public static String expect(String expectString) {
try {
int c = 0;
char[] buf = new char[4096];
//Here c will return the no. of chars read
while ((c = br.read(buf)) != -1) {
String tmp = "";
//converting that char array to String
for (int i = 0; i < c; i++) {
//Printing that character
System.out.print(buf[i]);
tmp += buf[i];
}
expectBuffer.append(tmp).append(NEW_LINE);
if (expectBuffer.toString().contains(expectString)) {
break;
}
}
String expBuff = expectBuffer.toString();
expectBuffer.setLength(0);
// System.out.println(expBuff);
return expBuff;
} catch (Exception e) {
System.out.println(e);
return "";
}
}
The problem i am facing is the no. of characters read by BufferedReader each time.
i.e. Each time I have to send some commands to the router and that is also being read by BufferedReader.
For eg.
send ("commandABC");
expect(prompt);
send ("command-efg");
expect(prompt);
send ("commandHij");
expect(prompt);
Based on the commands I am sending, it will show some output. Whatever I am sending, that is also being read and unfortunately, it is getting printed in a separate manner.
Like as below.
com
mandABC
<command output here>
command-
efg
<command output here>
commandHij
<command output here>
As i pointed out above, only the commands, whichever I am sending are getting printed in separate manner.
I have checked the no. of char read at that time and found that it is ranging from 2-10.
That is why it is getting printed in that manner.
Is there anyway to restrict the read at least a minimum of 100 chars?
Thanks in advance.
If you want to wait until you've read a full line of text, try bf.readLine() (you'd need to make sure each command was terminated by '\n'
If you want to make sure you've read a certain number of characters (say 100) before continuing processing, use a loop:
char buffer[128];
for (int charsRead = 0; charsRead < 100; ) {
charsRead += bf.read(buffer, charsRead, (100 - charsRead));
}
Note the (verbosified) syntax for bf.read():
bf.read(buffer, offset_size, max_to_read)
Passing charsRead as the offset size means each block of chars read will be stored right after the previously read ones. Passing (100 - charsRead) as max_to_read limits the total chars you read.
Source: API ref http://docs.oracle.com/javase/6/docs/api/java/io/BufferedReader.html#read(char[],%20int,%20int