I made an app to calculate file transporting time.
Here is my code:
for (File srcfile : fList) {
srcFileName = srcfile.getName();
sizeInMB = (srcfile.length() / (1024*1024));
srcFilePath = srcPath + "/" + srcFileName;
try
{
fis = new FileInputStream(srcFilePath);
tmp = fis.available();
bufDynmc = new byte[tmp];
while (true)
{
readStartTime = System.currentTimeMillis();
bytesRead = fis.read(bufDynmc);
readEndTime = System.currentTimeMillis();
readTimeSum += (readEndTime - readStartTime);
if (bytesRead > 0)
{
if(rsltCode == RESULT_OK)
{
treeUri = rsltData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
DocumentFile newFile = pickedDir.createFile("image/jpg", srcFileName);
fos = getContentResolver().openOutputStream(newFile.getUri());
writeStartTime = System.currentTimeMillis();
fos.write(bufDynmc, 0, bytesRead);
writeEndTIme = System.currentTimeMillis();
writeTimeSum += (writeEndTIme - writeStartTime);
}
continue;
} else break;
}
sizeSum += sizeInMB;
fis.close(); fos.close();
} catch (Exception e) {e.printStackTrace();}
rescanGallery(treeUri);
}
What I want to measure is how much time has been spend from source directory to RAM ,
and from RAM to destination directory.
Am I measuring the reading time and writing time with right method?
I'm not sure cuz this program gives me a time which is too fast.
Related
The library I'm using requires me to pass it a file path.
Currently, I use the Uri to create a new file (in an AsyncTask) as shown below:
#Override
protected String doInBackground(Uri... params) {
File file = null;
int size = -1;
try {
try {
if (returnCursor != null && returnCursor.moveToFirst()){
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
size = (int) returnCursor.getLong(sizeIndex);
}
}
finally {
if (returnCursor != null)
returnCursor.close();
}
if (extension == null){
pathPlusName = folder + "/" + filename;
file = new File(folder + "/" + filename);
}else {
pathPlusName = folder + "/" + filename + "." + extension;
file = new File(folder + "/" + filename + "." + extension);
}
BufferedInputStream bis = new BufferedInputStream(is);
FileOutputStream fos = new FileOutputStream(file);
byte[] data = new byte[1024];
long total = 0;
int count;
while ((count = bis.read(data)) != -1) {
if (!isCancelled()) {
total += count;
if (size != -1) {
publishProgress((int) ((total * 100) / size));
}
fos.write(data, 0, count);
}
}
fos.flush();
fos.close();
} catch (IOException e) {
errorReason = e.getMessage();
}
return file.getAbsolutePath();
}
As you can imagine, this might take some time depending on the file size.
Question
Is there any way to access the file without having to create/copy it?
*I have read that I can use ContentResolver and methods like openInputStream() and openOutputStream(). But this will only provide me with a stream and does not solve the issue I have of having to write a new file?
Extra info:
I get the Uri by passing the following to an Intent:
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
Then in onActivityResult I get the Uri by calling data.getData().
Please do not provide me with solutions like this one. I do not want to get a file Uri from a content Uri because it's unreliable and incorrect.
It looks pretty clear that a library that cannot handle a content scheme is of no use if you only have a content scheme.
You have to make a copy of the content in a file. As you do now.
I want to build android download speed test. To do that I am using TrafficStats class. Problem is that I am getting wrong results. Results are almost the same when I run the test but I put heavy load on my Internet connection before I run test. I download file for 30 seconds and after that (or when file is downloaded) and then calculate bytes using TrafficStats
Does someone knows where is the problem?
This is code that I am using:
#Override
protected String doInBackground(String... urls) {
String downloaded ="";
// String uploaded = "";
try{
long BeforeTime = System.currentTimeMillis();
long TotalTxBeforeTest = TrafficStats.getTotalTxBytes();
long TotalRxBeforeTest = TrafficStats.getTotalRxBytes();
URL url = new URL(urls[0]);
URLConnection connection = new URL(urls[0]).openConnection();
connection.setUseCaches(false);
connection.connect();
InputStream input = connection.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
byte[] buffer = new byte[1024];
int n = 0;
long endLoop = BeforeTime+30000;
while(System.currentTimeMillis() < endLoop) {
/* if (bufferedInputStream.read(buffer) != -1){
break;
}*/
}
long TotalTxAfterTest = TrafficStats.getTotalTxBytes();
long TotalRxAfterTest = TrafficStats.getTotalRxBytes();
long AfterTime = System.currentTimeMillis();
double TimeDifference = AfterTime - BeforeTime;
double rxDiff = TotalRxAfterTest - TotalRxBeforeTest;
double txDiff = TotalTxAfterTest - TotalTxBeforeTest;
Log.e(TAG, "Download skinuto. "+ rxDiff);
if((rxDiff != 0) && (txDiff != 0)) {
double rxBPS = (rxDiff / (TimeDifference/1000)); // total rx bytes per second.
double txBPS = (txDiff / (TimeDifference/1000)); // total tx bytes per second.
downloaded = String.valueOf(rxBPS) + "B/s. Total rx = " + rxDiff;
// uploaded = String.valueOf(txBPS) + "B/s. Total tx = " + txDiff;
}
else {
downloaded = "No downloaded bytes.";
}
}
catch(Exception e){
Log.e(TAG, "Error while downloading. "+ e.getMessage());
}
return downloaded;
}
I tried your code - it seems to work fine for me BUT i changed
while(System.currentTimeMillis() < endLoop) {
/* if (bufferedInputStream.read(buffer) != -1) {
break;
}*/
}
to
while(System.currentTimeMillis() < endLoop) {
if (bufferedInputStream.read(buffer) == -1){
break;
}
}
since read returns -1 if the end of the stream is reached.
I have been writing an updater for my game.
It checks a .version file on drop box and compares it to the local .version file.
If there is any link missing from the local version of the file, it downloads the required link one by one.
This is the error that it shows
Exception in thread "Thread-9" java.lang.OutOfMemoryError: Java heap space
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:209)
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:204)
at com.fox.listeners.ButtonListener.UpdateStart(ButtonListener.java:132)
at com.fox.listeners.ButtonListener$1.run(ButtonListener.java:58)
It only shows for some computers though and not all of them this is the readFile method
private byte[] readFile(URL u) throws IOException {
return readFile(u, getFileSize(u));
}
private static byte[] readFile(URL u, int size) throws IOException {
byte[] data = new byte[size];
int index = 0, read = 0;
try {
HttpURLConnection conn = null;
conn = (HttpURLConnection) u.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
InputStream is = conn.getInputStream();
progress_a = 0;
progress_b = data.length;
while(index < data.length) {
read = is.read(data, index, size-index);
index += read;
progress_a = index;
}
} catch(Exception e) {
e.printStackTrace();
}
return data;
}
private byte[] readFile(File f) {
byte[] data = null;
try {
data = new byte[(int)f.length()];
#SuppressWarnings("resource")
DataInputStream dis = new DataInputStream(new FileInputStream(f));
dis.readFully(data);
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
This is the main method that is ran
public void UpdateStart() {
System.out.println("Starting Updater..");
if(new File(cache_dir).exists() == false) {
System.out.print("Creating cache dir.. ");
while(new File(cache_dir).mkdir() == false);
System.out.println("Done");
}
try {
version_live = new Version(new URL(version_file_live));
} catch(MalformedURLException e) {
e.printStackTrace();
}
version_local = new Version(new File(version_file_local));
Version updates = version_live.differences(version_local);
System.out.println("Updated");
int i = 1;
try {
byte[] b = null, data = null;
FileOutputStream fos = null;
BufferedWriter bw = null;
for(String s : updates.files) {
if(s.equals(""))
continue;
System.out.println("Reading file "+s);
AppFrame.pbar.setString("Downloading file "+ i + " of "+updates.files.size());
if(progress_b > 0) {
s = s + " " +(progress_a * 1000L / progress_b / 10.0)+"%";
}
b = readFile(new URL(s));
progress_a = 0;
progress_b = b.length;
AppFrame.pbar.setString("Unzipping file "+ i++ +" of "+updates.files.size());
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(b));
File f = null, parent = null;
ZipEntry entry = null;
int read = 0, entry_read = 0;
long entry_size = 0;
progress_b = 0;
while((entry = zipStream.getNextEntry()) != null)
progress_b += entry.getSize();
zipStream = new ZipInputStream(new ByteArrayInputStream(b));
while((entry = zipStream.getNextEntry()) != null) {
f = new File(cache_dir+entry.getName());
if(entry.isDirectory())
continue;
System.out.println("Making file "+f.toString());
parent = f.getParentFile();
if(parent != null && !parent.exists()) {
System.out.println("Trying to create directory "+parent.getAbsolutePath());
while(parent.mkdirs() == false);
}
entry_read = 0;
entry_size = entry.getSize();
data = new byte[1024];
fos = new FileOutputStream(f);
while(entry_read < entry_size) {
read = zipStream.read(data, 0, (int)Math.min(1024, entry_size-entry_read));
entry_read += read;
progress_a += read;
fos.write(data, 0, read);
}
fos.close();
}
bw = new BufferedWriter(new FileWriter(new File(version_file_local), true));
bw.write(s);
bw.newLine();
bw.close();
}
} catch(Exception e) {
e.printStackTrace();
return;
}
System.out.println(version_live);
System.out.println(version_local);
System.out.println(updates);
CacheUpdated = true;
if(CacheUpdated) {
AppFrame.pbar.setString("All Files are downloaded click Launch to play!");
}
}
I don't get why it is working for some of my players and then some of my other players it does not i have been trying to fix this all day and i am just so stumped at this point but this seems like its the only big issue left for me to fix.
Either increase the memory allocated to your JVM (How can I increase the JVM memory?), or make sure that the file being loaded in memory isn't gigantic (if it is, you'll need to find an alternate solution, or just read chunks of it at a time instead of loading the entire thing in memory).
Do your update in several steps. Here's some pseudo-code with Java 8. It's way shorter than what you wrote because Java has a lot of built-in tools that you re-write much less efficiently.
// Download
Path zipDestination = Paths.get(...);
try (InputStream in = source.openStream()) {
Files.copy(in, zipDestination);
}
// Unzip
try (ZipFile zipFile = new ZipFile(zipDestination.toFile())) {
for (ZipEntry e: Collections.list(zipFile.entries())) {
Path entryDestination = Paths.get(...);
Files.copy(zipFile.getInputStream(e), entryDestination);
}
}
// Done.
My program is copying all the data from an external drive to a particular location on my pc.
Here is my program :-
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy
{
public static void main(String[] args)
{
String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I"};
File[] drives = new File[letters.length];
int copy=0;int l;File files[]=null;boolean pluggedIn=false;
FileInputStream fis=null;
FileOutputStream fos=null;
boolean[] isDrive = new boolean[letters.length];
for (int i = 0; i < letters.length; ++i)
{
drives[i] = new File(letters[i] + ":/");
isDrive[i] = drives[i].canRead();
}
System.out.println("FindDrive: waiting for devices...");
while (true)
{
try
{
for (int i = 0; i < letters.length; ++i)
{
pluggedIn = drives[i].canRead();
if (pluggedIn != isDrive[i])
{
if (pluggedIn)
{
System.out.println("Drive " + letters[i] + " has been plugged in");
files = drives[i].getAbsoluteFile().listFiles();
File file;
int fread;
for (l = 0; l < files.length; l++)
{
if (files[l].isFile())
{
file = new File("G://copied//" + files[l].getName());
file.createNewFile();
fis = new FileInputStream(drives[i].getAbsolutePath() + files[l].getName());
fos = new FileOutputStream(file);
while (true)
{
fread = fis.read();
if (fread == -1)
{
break;
}
fos.write(fread);
}
}
else
{
func(files[l].getAbsoluteFile(), "G://copied");
}
if(l==files.length-1)
{
System.out.print("copy complete");
fos.close();
fis.close();
}
}
}
else
{
System.out.println("Drive " + letters[i] + " has been unplugged");
}
isDrive[i] = pluggedIn;
}
}
Thread.sleep(5000);
}
catch (FileNotFoundException e) { }
catch (IOException e) { }
catch (InterruptedException e) {}
}
}
public static void func(File dir, String path)
{
File file = new File(path + "//" + dir.getName());
file.mkdir();
File[] files = dir.listFiles();
FileInputStream fis;
FileOutputStream fos;
int fread;
File file1;
for (int i = 0; i < files.length; i++)
{
if (files[i].isFile())
{
file1 = new File(file.getAbsolutePath() + "//" + files[i].getName());
try
{
file1.createNewFile();
fis = new FileInputStream(files[i]);
fos = new FileOutputStream(file1);
while (true)
{
fread = fis.read();
if (fread == -1)
{
break;
}
fos.write(fread);
}
} catch (FileNotFoundException e) {} catch (IOException e) {}
}
else
{
func(files[i], file.getAbsolutePath());
}
}
}
}
Now it is taking too long to copy large files.
Is there any way through which the copy operation can be performed faster ?
Thanx in advance for any suggestion.
If you can use Java 7 or later: java.nio.file.Files#copy.
If you are stuck with older Java: java.nio.channels.FileChannel#transferTo
A basic example that obtains FileChannel instances from the file streams:
public void copy( FileInputStream fis, FileOutputStream fos ) throws IOException {
FileChannel fic = fis.getChannel();
FileChannel foc = fos.getChannel();
long position = 0;
long remaining = fic.size();
while ( remaining > 0 ) {
long transferred = fic.transferTo( position, remaining, foc );
position += transferred;
remaining -= transferred;
}
}
You have to use a buffer. The copy logic should be something like:
byte[] buffer = new byte[4096];
int n;
while ((n = input.read(buffer) != -1)
{
output.write(buffer, 0, n);
}
output.close();
input.close();
This way, you copy a chunk of 4096 bytes at once, instead of byte per byte.
file.createNewFile();
Remove that. It is redundant. new FileOutputStream() will do that anyway. You're just adding processing here, and disk processing at that.
fis = new FileInputStream(drives[i].getAbsolutePath() + files[l].getName());
fos = new FileOutputStream(file);
Now add:
int count;
byte[] buffer = new byte[8192]; // or much more if you can afford the space
while ((count = fis.read(buffer)) > 0)
{
fos.write(buffer, 0, count);
}
Back to your code:
while (true)
{
fread = fis.read();
if (fread == -1)
{
break;
}
fos.write(fread);
}
Remove all that. Reading a byte at a time is as inefficient as it gets.
I am reading a .jpg file over InputStream using this code but I am receiving NULNUL...n stream after some text. Ii am reading this file link to file and link of file that I received , link is Written File link.
while ((ret = input.read(imageCharArray)) != -1) {
packet.append(new String(imageCharArray, 0, ret));
totRead += ret;
imageCharArray = new char[4096];
}
file = new File(
Environment.getExternalStorageDirectory()
+ "/FileName_/"
+ m_httpParser.filename + ".jpg");
PrintWriter printWriter = new PrintWriter(file);
// outputStream = new FileOutputStream(file); //also Used FileoutputStream for writting
// outputStream.write(packet.toString().getBytes());//
// ,
printWriter.write(packet.toString());
// outputStream.close();
printWriter.close();
}
I have also tried FileoutputStream but hardlucj for this too as commented in my code.
Edit
I have used this also. I have a content length field upto which i am reading and writing
byte[] bytes = new byte[1024];
int totalReadLength = 0;
// read untill we have bytes
while ((read = inputStream.read(bytes)) != -1
&& contentLength >= (totalReadLength)) {
outputStream.write(bytes, 0, read);
totalReadLength += read;
System.out.println(" read size ======= "
+ read + " totalReadLength = "
+ totalReadLength);
}
String is not a container for binary data, and PrintWriter isn't a way to write it. Get rid of all, all, the conversions between bytes and String and vice versa, and just transfer the bytes with input and output streams:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
If you need to constrain the number of bytes read from the input, you have to do that before calling read(), and you also have to constrain the read() correctly:
while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length: (int)(length-total))) > 0)
{
total += count;
out.write(buffer, 0, count);
}
I tested it in my Nexus4 and it's working for me. Here is the snippet of code what I tried :
public void saveImage(String urlPath)throws Exception{
String fileName = "kumar.jpg";
File folder = new File("/sdcard/MyImages/");
// have the object build the directory structure, if needed.
folder.mkdirs();
final File output = new File(folder,
fileName);
if (output.exists()) {
output.delete();
}
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlPath);
stream = url.openConnection().getInputStream();
// InputStreamReader reader = new InputStreamReader(stream);
DataInputStream dis = new DataInputStream(url.openConnection().getInputStream());
byte[] fileData = new byte[url.openConnection().getContentLength()];
for (int x = 0; x < fileData.length; x++) { // fill byte array with bytes from the data input stream
fileData[x] = dis.readByte();
}
dis.close();
fos = new FileOutputStream(output.getPath());
fos.write(fileData);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Just Call the above function in a background thread and pass your url. It'll work for sure. Let me know if it helps.
You can check below code.
destinationFile = new File(
Environment.getExternalStorageDirectory()
+ "/FileName_/"
+ m_httpParser.filename + ".jpg");
BufferedOutputStream buffer = new BufferedOutputStream(new FileOutputStream(destinationFile));
byte byt[] = new byte[1024];
int i;
for (long l = 0L; (i = input.read(byt)) != -1; l += i ) {
buffer.write(byt, 0, i);
}
buffer.close();