I'm developing an Android application sending files from one device to another.
Establishing the connection between both devices works perfectly, but there is something going wrong while transferring the file.
On the receiving device, the file gets created but unfortunately it's empty.
This is my code for handling the incoming file:
try {
byte[] buffer = new byte[1024];
int bytes = 0;
boolean eof = false;
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "test.jpg");
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (!eof) {
bytes = mmInStream.read(buffer);
int offset = bytes - 11;
byte[] eofByte = new byte[11];
eofByte = Arrays.copyOfRange(buffer, offset, bytes);
String message = new String(eofByte, 0, 11);
if(message.equals("end of file")) {
os.flush();
os.close();
eof = true;
} else {
os.write (buffer);
}
}
} catch (IOException e) {
e.printStackTrace();
}
Using the DataInputStream/DataOuputStream solved the problem.
Related
I encrypted multiple files in one file in order.
Now I want to decrypt only one of those files. for this purpose I did this:
I got all bytes of encrypted files as array Like this: (first index: byte offset of every file in the encrypted file, second index: length of file bytes in the encrypted file)
int[] file1 = new int[] {0 ,109624}
int[] file2 = new int[] {109624,40480}
int[] file3 = new int[] {150104,153640}
int[] file4 = new int[] {303744,24320}
Now for getting specific file from the encrypted file and decrypt it I should to read the encrypted file. First of all, skip the bytes of previous files.
for skipping them I use this method (for example I want to encrypt file2):
int fromByte = file2[0];
int fileLength = file2[1];
FileInputStream fis = new FileInputStream(sourceFile);
CipherInputStream cis = new CipherInputStream(fis,cipher);
long skipBytes = cis.skip(fromByte);
Then it reads byte to byte of source file in "while" loop and when length of read file bytes equals to fileLength, it breaks loop.
I brought all the codes at the end here.
When I decrypt first file (from byte:0 and file length:109624 and it dosn't need to "skip bytes"), It works well.
But when I decrypt other files (for example for encrypt file2 it needs to skipt 109624 byte from source file), It doesn't work well and created file is not decrypted.
Why it dosn't work for other files?
Here's my codes:
public void decryptFile(File sourceFile, File targetFile, int fromByte, int lengthToRead, SecretKeySpec keySpec) {
try {
FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(targetFile);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,keySpec);
CipherInputStream cis = new CipherInputStream(fis,cipher);
int readPart,currentLength = 0, bufferSize = 8;
long skipBytes;
byte[] bytes = new byte[bufferSize];
skipBytes = cis.skip(fromByte);
while ((readPart = cis.read(bytes)) != -1) {
fos.write(bytes,0,readPart);
currentLength += bufferSize;
if (currentLength >= lengthToRead) {
break;
}
}
cis.close();
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
Here's My codes for encrypt multiple files in on file:
public void encryptFile(File[] sourceFiles, File targetFile, SecretKeySpec keySpec) {
try {
FileOutputStream fos = new FileOutputStream(targetFile);
FileInputStream fis;
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,keySpec);
CipherOutputStream cos = new CipherOutputStream(fos,cipher);
int readPart,bufferSize = 8;
byte[] bytes = new byte[bufferSize];
for (File sourceFile : sourceFiles) {
fis = new FileInputStream(sourceFile);
while ((readPart = fis.read(bytes)) != -1) {
cos.write(bytes, 0, readPart);
}
fis.close();
}
cos.flush();
cos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
I realized the problem, After many reviews.
There are two problem in this codes:
problem 1: in skip method. we should check the skipBytes and if it is not equal to fromByte, it must repeat. for this purpose add these codes:
while (skipBytes<fromByte) {
fromByte -= skipBytes;
skipBytes = cis.skip(fromByte);
}
problem 2: in encrypt function. if the file length is not multiple of 8, encryption method add some bytes until its length is multiple of 8. for fix this problem we should to add those bytes to the file ourselves before encrypt it. for this purpose add these codes before encrypt every file:
int remaining = (int) (sourceFile.length() % 8);
if (remaining>0) {
BufferedWriter bw = new BufferedWriter(new FileWriter(sourceFile,true));
while (remaining<8) {
bw.write(" ");
remaining++;
}
bw.close();
}
This codes modifies source file. If you want to don't modifying source file, instead of above codes, use this codes after ending encryption while loop:
int remainder = (int)(sourceFile.length() % 8);
if (remainder>0) {
StringBuilder sb = new StringBuilder("");
while (remainder<8) {
sb.append(" ");
remainder++;
}
byte[] additionBytes = sb.toString().getBytes(Charset.forName("UTF-8"));
cos.write(additionBytes, 0, additionBytes.length);
}
I'm trying to receive a Picture on my Android phone from Server using socket programming.I use this code but in.read() in 4th line always returns -1.
How can I fix this problem?
Client Code:
try {
x = new byte[picLength2];
int current = 0;
int byteRead = in.read(x, 0, x.length);
current = byteRead;
do {
byteRead = in.read(x, current, (x.length - current));
if (byteRead >0) {
current += byteRead;
}
} while (byteRead > -1);
}catch (IOException e){
e.printStackTrace();
}
Server Code:
try {
File myFile = new File("C:/onlinegame/null.jpg");
mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.write(mybytearray);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
I want to let the user download a file from my android app with the web browser on his computer (in local network).
At first I wrote the code for this feature in eclipse on my computer and it worked fine. But when I try to run it in an android app (the file is copied from the assets path) I am not able to download the file anymore. Firefox just tells me that it couldnt download because the source file could not be read.
This ist my code in the app. It doesnt throw any errors.
public class test implements Runnable {
public boolean running = true;
ServerSocket servsock = null;
Context context;
String filename = "test.jar";
public test(Context con){
this.context=con;
}
public Integer createSocketandStart(){
for (int i=1234; i<2000; ++i){
try{
servsock = new ServerSocket(i);
servsock.setSoTimeout(1000000);
new Thread(this).start();
return i;
}catch(Exception e){
System.out.print("socket error");
}
}
return null;
}
public void run(){
File f= new File(context.getFilesDir(), filename);
try {
InputStream is = context.getAssets().open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) { throw new RuntimeException(e); }
while (running) {
try {
Socket connection = servsock.accept();
OutputStream out = new BufferedOutputStream(connection.getOutputStream());
PrintStream pout = new PrintStream(out);
InputStream file = new FileInputStream(f);
pout.print("HTTP/1.0 200 OK\r\n" +
"Content-Type: application/octet-stream\r\n" +
"Content-Disposition: attachment; filename=\"" + filename + "\"\r\n" +
"Date: " + new Date() + "\r\n" +
"Server: FileServer 1.0\r\n\r\n");
byte[] buffer = new byte[1000];
while (file.available() > 0) {
out.write(buffer, 0, file.read(buffer));
}
out.flush();
if (connection != null) connection.close();
file.close();
pout.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
I am creating an app that needs to read data from a file. I was initially reading it from the assets folder using a BufferedReader and an InputStreamReader but I was running into memory issues (see Android: File Reading - OutOfMemory Issue). One suggestion was to copy the data from the assets folder to the internal storage (not the SD card) and then access it via RandomAccessFile. So I looked up how to copy files from the assets to internal storage and I found 2 sources:
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/RpXiMYV48Ww
http://developergoodies.blogspot.com/2012/11/copy-android-asset-to-internal-storage.html
I decided to use the code from the second one and modified it for my file. So it looks like this:
public void copyFile() {
//Open your file in assets
Context context = getApplicationContext();
String destinationFile = context.getFilesDir().getPath() + File.separator + "text.txt";
if (!new File(destinationFile).exists()) {
try {
copyFromAssetsToStorage(context, "text.txt", destinationFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int length = Input.read(buffer);
while (length > 0) {
output.write(buffer, 0, length);
length = input.read(buffer);
}
}
private void copyFromAssetsToStorage(Context context, String sourceFile, String destinationFile) throws IOException {
InputStream inputStream = context.getAssets().open(sourceFile);
OutputStream outputStream = new FileOutputStream(destinationFile);
copyStream(inputStream , outputStream );
outputStream.flush();
outputStream.close();
inputStream.close();
}
I am assuming that this copies the file into the app's data directory. I have not been able to test it because I would like to be able to access the file using RandomAccessFile. However, I have never done either one of these two (copying the file from assets and RandomAccessFile) so I am stuck. The work on this app has come to a standstill because this is the only thing that is preventing me from completing it.
Can anyone provide me with corrections, suggestions, and correct implementations of how to access the data using RandomAccessFile? (The data is a list of strings 4-15 characters in length on each line.)
EDIT*
private File createCacheFile(Context context, String filename){
File cacheFile = new File(context.getCacheDir(), filename);
if (cacheFile.exists()) {
return cacheFile ;
}
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
try {
inputStream = context.getAssets().open(filename);
fileOutputStream = new FileOutputStream(cacheFile);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
while ( (length = inputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer,0,length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return cacheFile;
}
1- Copy the file from assets to the cache directory
This code just for illustration, you have to do appropriate exception handling and close resources
private File createCacheFile(Context context, String filename){
File cacheFile = new File(context.getCacheDir(), filename);
if (cacheFile.exists()) {
return cacheFile ;
}
InputStream inputStream = context.getAssets().open(filename);
FileOutputStream fileOutputStream = new FileOutputStream(cacheFile);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
while ( (length = inputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer,0,length);
}
fileOutputStream.close();
inputStream.close();
return cacheFile;
}
2- Open the file using RandomAccessFile
File cacheFile = createCacheFile(context, "text.txt");
RandomAccessFile randomAccessFile = new RandomAccessFile(cacheFile, "r");
// Process the file
randomAccessFile.close();
On a side note, you should follow Java naming conventions, e.g. your method and variable name should start with small letter such as copyFromAssetsToStorage and destinationFile
Edit:
You should make a separate try/catch for each close() operation, so if one fails the other still get executed and check that they are not null
finally {
try {
if(fileOutputStream!=null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(inputStream!=null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
I tried writing a file to my android phone using phonegap ui.
I have given the write permission and i tried by using getExternalStorageDirectory() and by giving the absolute path. But still not able to write it.
s1 is the name of the file that i am writing in the external storage
Environment.getExternalStorageState();
//File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"/Android/");
File file = new File("/mnt/sdcard"+ File.separator + "Android" + File.separator);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("TravellerLog :: ", "Problem creating Folder");
}
}
Environment.getExternalStorageState();
File outputFile = new File(file, s1);
FileOutputStream fileoutputstream = new FileOutputStream(outputFile);
byte abyte0[] = new byte[1024];
for (int i = 0; (i = inputstream.read(abyte0)) > 0;)
fileoutputstream.write(abyte0, 0, i);
fileoutputstream.close();
inputstream.close();
I wrote a quick working demo of writing a file to the external storage.
If this still doesn't work maybe it is a phonegap specific issue.
Hope this helps:
InputStream is = null;
OutputStream os = null;
byte[] buffer = new byte[2048];
int bytes_read = 0;
File inputFile = new File("/init.rc");
File outputFile = new File(Environment.getExternalStorageDirectory() + "/testfile");
try
{
is = new FileInputStream(inputFile);
os = new FileOutputStream(outputFile);
while ((bytes_read = is.read(buffer)) != -1)
{
os.write(buffer, 0, bytes_read);
}
}
catch (Exception ignore) {}
finally
{
try
{
is.close();
}
catch (Exception ignore) {}
try
{
os.close();
}
catch (Exception ignore) {}
}
if (outputFile.exists())
{
Toast.makeText(this, "Success!", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(this, "Failure!", Toast.LENGTH_LONG).show();
}