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.
Related
I am trying to read in the contents of a file byte by byte individually. TO do this, I'm using the DataInputStream's readByte() method. However, after I do this, I need to see if the byte it read in was originally a char or an int so I can store it appropriately. So basically, when reading a file I need to be able to check what the next character's primitive datatype is before converting it to a byte to read. Alternativly, I could somehow check the next character before I read it in, then if it's an int use readInt() or if its a char use readChar().
Here is my current code:
public class Lexer {
public static void main(String a[]) {
try {
File file = new File("placeholder.txt");
DataInputStream is = new DataInputStream(new FileInputStream(file));
char c;
int i;
byte b;
while((b = is.readByte()) != -1) {
//here, I would like to now store my byte to c, or i based on what type it
// originally was.
}
} catch(FileNotFoundException e) {
System.out.println("Fatal Error: Could not find program source code file");
} catch (IOException e) {
System.out.println("Fatal Error: Could not i/o with source code file");
}
}
//}
}
File Contents:
javarocks1234! //while reading, I need to know if the next byte I read in was a char or an int in this file
you can try something like,
String readtxt = "9999"; // reading string from file
java.util.regex.Pattern numberPatter = java.util.regex.Pattern.compile(".*[^0-9].*");
if( numberPatter .matcher(readtxt).matches() )
System.out.println("it's numeric");
else
System.out.println("It's not a numeric");
I have made reference from this question and achieved success in setting up encryption. I am trying to however utilize this encryption on a string of array to write into a file. This is how I am setting my method up but I end up writing only one of the string array into the file.
String[] str = new String ["X: Adam", "Y: Barry", "z: Oliver"];
File file = new File(Path + "/EncryptedFile.txt);
Calling method to write the string array into the file: Crypto.WriteEncrypteFile(str, file);
The method
Public void WriteEncrypteFile(String[] str, File file) {
try {
BufferedWriter w = new BufferedWriter(new FileWriter(file));
byte[] tmptxt = Array.toString(str).getbytes(Charset.forName(" UTF-8 "));
byte[] encTxt = cipher.doFinal(tmptxt);
w.write(string.valueOf(encTxt));
w.flush();
w.close();
} catch (Exception e){
e.printStackTrace();
}
My questions is how can I write an encrypted string from my array into the file. Any pointers?
You are just writing the String value of the array to the file (since you use Array.toString(str)). This will usually just be some representation of the reference. You have to either concatenate the values of the array or loop through it and encrypt/write every value individually.
Additionally, you shouldn't use a Writer to write content that does not consist of characters. Writers always try to encode the output which could potentially ruin your carefully set up bytes.
Just use a FileOutputStream and write the bytes with that:
try( FileOutputStream fos = new FileOutputStream(file) ) {
for(String s : str) {
byte[] tmptxt = s.getbytes(Charset.forName("UTF-8"));
byte[] encTxt = cipher.doFinal(tmptxt);
w.write(encTxt);
}
} catch(IOException e) {
// print error or whatever
}
For reading you do the same thing but with a FileInputStream instead.
You can use Arrays.toString(), but this way you will need to parse it to read it. Alternatively you can also write the byte[] directly in the file using an OutputStream. There's no need to convert to a string unless you want a human (e.g. yourself) to read it.
I want to read binary file in java. I have 153(1.bin, 2.bin...153.bin) bin file. I must read that. I thought that I must use ArrayList for buffering. But I could not do that. How can I do this ?
After some research, I found that way in this title(Reading a binary input stream into a single byte array in Java). There is code like below in this title.
StringBuilder sb = new StringBuilder();
String fileName = "/path/10.bin";
byte[] buffer;
try {
buffer = Files.readAllBytes(Paths.get(fileName));
for(byte b : buffer){
sb.append(String.format("%02X ", b));
}
System.out.println(sb.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Is it true way for my question or do I must use Arraylist for buffering ? If I use single byte array for buffering, do I must clear the buffer for the other binary files.
Edit : 153 unit means 153 file(1.bin,2.bin ... 153.bin)
Your question is unclear. For one, you don't tell what those "units" are, how long they are etc. Second, all your code does is dump the contents of the file in hexadecimal.
What I suggest you do here is map the file into memory and use a class to wrap that around, and make it implement Closeable.
See FileChannel.open() and FileChannel.map(). Please note however that it is unsafe to map more than 1 GiB in memory. This is not a "real" mmap().
I'm not sure what you mean by "units". Byte data is read something like that:
File f = new File ("File.txt");
FileInputStream fis = new FileInputStream (f);
byte[] bytes = new byte[(int) f.length ()];
fis.read (bytes, 0, (int) f.length () );
Make sure your File is not too big.
I'm assuming a unit is one byte. Is this correct?
An ArrayList is not appropriate for byte buffering. It is a wrapper class for an array that implements the List interface (by which most of it's power is defined.)
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
If you simply want to read bytes in from a file, you could use FileInputStream.
http://docs.oracle.com/javase/tutorial/essential/io/bytestreams.html
Here's a simple example that reads input from a file containing "hello world!"
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Input {
public static void main(String[] args) throws FileNotFoundException, IOException {
try (FileInputStream in = new FileInputStream("test.txt")) {
int c;
while ( (c = in.read()) != -1 )
System.out.print((byte)c + " ");
}
}
}
Output in bytes: 104 101 108 108 111 32 119 111 114 108 100 33 13 10
my problem is to read non primes from txt file and write prime factors in same file.
i actually dont know how BufferedReader works.from my understanding i am trying to read the file data to buffer(8kb) and write prime factors to file.(by creating a new one)
class PS_Task2
{
public static void main(String[] args)
{
String line=null;
int x;
try
{
FileReader file2 = new FileReader("nonprimes.txt");
BufferedReader buff2=new BufferedReader(file2);
File file1 = new File("nonprimes.txt");
file1.createNewFile();
PrintWriter d=new PrintWriter(file1);
while((line = buff2.readLine()) != null)
{
x=Integer.parseInt(line);
d.printf ("%d--> ", x);
while(x%2==0)
{
d.flush();
d.print("2"+"*");
x=x/2;
}
for (int i = 3; i <= Math.sqrt(x); i = i+2)
{
while (x%i == 0)
{
d.flush();
d.printf("%d*", i);
x = x/i;
}
}
if (x > 2)
{
d.flush();
d.printf ("%d ", x);
}
d.flush();//FLUSING THE STREAM TO FILE
d.println("\n");
}
d.close(); // CLOSING FILE
}
feel free to give detailed explanation. :D thanks ~anirudh
reading and writing to a file in java doesnt EDIT the file, but clear the old one and creates a new one, you can use many approachesfor example, to get your data, modify it, and either save it on memory in a StringBuilder or a collection or what ever and re-write it again
well i created fileOne.txt containing the following data :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
and i want to multiply all those numbers by 10, then re-write them again :
public static void main(String [] args) throws Exception{ // just for the example
// locate the file
File fileOne = new File("fileOne.txt");
FileReader inputStream = new FileReader(fileOne);
BufferedReader reader = new BufferedReader(inputStream);
// create a LinkedList to hold the data read
List<Integer> numbers = new LinkedList<Integer>();
// prepare variables to refer to the temporary objects
String line = null;
int number = 0;
// start reading
do{
// read each line
line = reader.readLine();
// check if the read data is not null, so not to use null values
if(line != null){
number = Integer.parseInt(line);
numbers.add(number*10);
}
}while(line != null);
// free resources
reader.close();
// check the new numbers before writing to file
System.out.println("NEW NUMBERS IN MEMORY : "+numbers);
// assign a printer
PrintWriter writer = new PrintWriter(fileOne);
// write down data
for(int newNumber : numbers){
writer.println(newNumber);
}
// free resources
writer.flush();
writer.close();
}
this approach is not very good when dealing with massive data
As per your problem statement, you need to take input from a file, do some processing and write back the processed data in the same file. For this, please note the below points:
You may not create a file with same name in a directory, so you must create the new file at some other location; or write the content into different file and later rename it after deleting original one.
While your file is open for reading, modifying the same file is not a good idea. you could use below approach:
Read the content of the file and store in a data structure liek Arrays, ArrayList.
Close the file.
Process the data stored in the data structure.
Open the file in write mode (over-write mode rather than append mode)
Write back the processed data into the file.
In the last section of the code I print what the Reader gives me. But its just bogus, where did I go wrong?
public static void read_impl(File file, String targetFile) {
// Create zipfile input stream
FileInputStream stream = new FileInputStream(file);
ZipInputStream zipFile = new ZipInputStream(new BufferedInputStream(stream));
// Im looking for a specific file/entry
while (!zipFile.getNextEntry().getName().equals(targetFile)) {
zipFile.getNextEntry();
}
// Next step in api requires a reader
// The target file is a UTF-16 encoded text file
InputStreamReader reader = new InputStreamReader(zipFile, Charset.forName("UTF-16"));
// I cant make sense of what this print
char buf[] = new char[1];
while (reader.read(buf, 0, 1) != -1) {
System.out.print(buf);
}
}
I'd guess that where you went wrong was believing that the file was UTF-16 encoded.
Can you show a few initial byte values if you don't decode them?
Your use of a char array is a bit pointless, though at first glance it should work. Try this instead:
int c;
while ((c = reader.read()) != -1) {
System.out.print((char)c);
}
If that does not work either, then perhaps you got the wrong file, or the file does not contain what you think it does, or the console can't display the characters it contains.