I'm trying to get save a text file from the internet into a folder in my res directory (res/files) so I can then read and interpret it. My android manifest has set the appropiate permissions but when I test it in the simulator it fails.
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
Here's the method to get the file:
public void getTextFile(){
String path ="http://hullmc.org.uk/cjvize/test.txt";
URL u = null;
try {
u = new URL(path);
BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream()));
int i = 0;
String replicated = "";
do{
String str = in.readLine();
replicated = replicated + "/n" + str;
i++;
}while(i<85);
in.close();
}
catch(Exception e){
welcome.setText("Failed");
}
}
Can anyone suggest why this is not working? Many thanks!
This is working fine for me :
Use of class variable for View and Activity allow to keep code centralaized and shared, passing view as parameter, updated in constructor :)
1) Code to store the file locally
View newReport;
Activity reportActivity;
private void downloadFile(String fileUrl, String fileName) {
try{
InputStream is = (InputStream) new URL(fileUrl).getContent();
FileOutputStream output = reportActivity.openFileOutput(fileName, newReport.getContext().MODE_PRIVATE);
byte data[] = new byte[1024];
int count;
while ((count = is.read(data)) != -1)
output.write(data, 0, count);
output.flush();
output.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
It saves the file on the internal storage.
Then to save a file from URL, just call:
downloadFile(myFileUrl, mySaveToFileName);
And to list your local files available:
String[] fileList = newReport.getContext().fileList();
for (String s : fileList){
System.out.println("File found : "+s);
}
Note: you do not require to save it locally to read it. If you prefer just to read it (to extract some info), let me know.
2) Code to "read and save to database", this should resolve:
// After InputStream declaration:
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
//TODO Update database row concatenating inputLine to existing text value.
}
in.close();
in=null;
is.close();
you can't save into the resource folder of your app. you can't even store files into the assets folder.
there aren't even such folders when you install the app - they are all zipped into the APK . the res folder is a special one too, because each file there also creates a constant in the "R.java" file, so that it would be easier to reach and use. you can't reach such a thing when it's dynamic...
what you can do is to choose the right folder for you (read here), and download the file into there, using something like this :
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(fullFilePath);
byte data[] = new byte[1024];
int count;
while ((count = input.read(data)) != -1)
output.write(data, 0, count);
//todo close streams and handle exceptions
if you use Apache commons library, you could minimize the code to just one line:
IOUtils.copy(new BufferedInputStream(url.openStream()), new FileOutputStream(fullFilePath));
Related
How we can push multiple files from our local folder to smb share folder using java. I can do with my single file using smbFile and it is working. I am looking for pushing multiple file push to smb share.
Any reference links and sample code would be helpful.
Thanks.
EDIT, Reference of code :
SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern);
if (files == null)
return false;
output(sb, logger, " Source file count: " + files.length);
String destFilename;
FileOutputStream fileOutputStream;
InputStream fileInputStream;
byte[] buf;
int len;
for (SmbFile smbFile: files) {
destFilename = destinationPath + smbFile.getName();
output(sb, logger, " copying " + smbFile.getName());
try {
fileOutputStream = new FileOutputStream(destFilename);
fileInputStream = smbFile.getInputStream();
buf = new byte[16 * 1024 * 1024];
while ((len = fileInputStream.read(buf)) > 0) {
fileOutputStream.write(buf, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
} catch (SmbException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e);
e.printStackTrace();
return false;
}
This works fine if i try to send one single file of anyformat. But if would like to send multiple file to smb share fromocal folder. For This i need thr help please. Thanks.
Try to declare a SmbFile object that is a root folder of your folder, that you want to upload to the shared folder. Then iterate through the root.listFiles() array.
Put the uploadable files in that folder.
I assume that, your SmbFile[] files array only contains one file if it's only uploading one file.
Or another possible solution is that, try to use SmbFileOutputStream and SmbFileInputStream instead of FileOutputStream and FileInputStream.
I'm guessing you are using jcifs-library (which is quite outdated), so firstly I would recommend you to switch library. I switched to SMBJ and here is how I'm uploading file:
private static void upload(File source, DiskShare diskShare, String destPath, boolean overwrite) throws IOException {
try (InputStream is = new java.io.FileInputStream(source)) {
if (destPath != null && is != null) {
// https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files
Set<AccessMask> accessMask = new HashSet<>(EnumSet.of(
AccessMask.FILE_READ_DATA,
AccessMask.FILE_WRITE_DATA, AccessMask.DELETE));
Set<SMB2ShareAccess> shareAccesses = new HashSet<>(
EnumSet.of(SMB2ShareAccess.FILE_SHARE_WRITE));
Set<FileAttributes> createOptions = new HashSet<>(
EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL));
try (com.hierynomus.smbj.share.File file = diskShare
.openFile(destPath, accessMask, createOptions,
shareAccesses,
(overwrite
? SMB2CreateDisposition.FILE_OVERWRITE_IF
: SMB2CreateDisposition.FILE_CREATE),
EnumSet.noneOf(SMB2CreateOptions.class))) {
int bufferSize = 2048;
if (source.length() > 20971520l) {
bufferSize = 131072;
}
byte[] buffer = new byte[bufferSize];
long fileOffset = 0;
int length = 0;
while ((length = is.read(buffer)) > 0) {
fileOffset = diskShare.getFileInformation(destPath)
.getStandardInformation().getEndOfFile();
file.write(buffer, fileOffset, 0, length);
}
file.flush();
file.close();
} finally {
is.close();
}
}
}
}
Of course takes a little effort on connecting the SMB-server and authenticating before this, but that's another case...
I'm using Eclipse for a university project making an android app.
I'm having a problem with 1 thing:
I have created a class called TextFileHandler.
The idea is that the app instantiates TextFileHandler and uses the methods
to read and write the text files within the app with get methods simply
returning a string value and set methods writing new values to the text files.
When this class is instantiated the constructor creates a text file.
The methods are supposed to access the created text files and read and write them
but the problem is, once it creates the text files it can't seem to access them
and the app just crashes.
I have included the constructor and then directly after the method getMeds()
which just crashes every time. I'm not sure why it can't find the text files.
Any help would be appreciated.
constructor:
public TextFileHandler(Context ctx){
this.context = ctx;
//create the medicine text file
String medtext = "1#Med*2#Med*3#Med*4#Med*5#Med*";
try {
File file = new File("Medicine.txt");
//if the file doesn't already exist then create it
//this is to make sure the app saves state
if(!file.exists()){
BufferedWriter output = new BufferedWriter(new FileWriter(file));
output.write(medtext);
output.close();
}
} catch ( IOException e ) {
e.printStackTrace();
}
String remtext = "1a#000000*1b#000000*1c#000000*1d#000000*1e#000000*";
remtext += "2a#000000*2b#000000*2c#000000*2d#000000*2e#000000*";
remtext += "3a#000000*3b#000000*3c#000000*3d#000000*3e#000000*";
remtext += "4a#000000*4b#000000*4c#000000*4d#000000*4e#000000*";
remtext += "5a#000000*5b#000000*5c#000000*5d#000000*5e#000000*";
try {
File file = new File("Reminder.txt");
//if the file doesn't already exist then create it
//this is to make sure the app saves state
if(!file.exists()){
BufferedWriter output = new BufferedWriter(new FileWriter(file));
output.write(remtext);
output.close();
}
} catch ( IOException e ) {
e.printStackTrace();
}
}
get method:
public String getMeds() throws IOException{
FileInputStream in = openFileInput("Medicine.txt");
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
String ret = sb.toString();
return ret;
}
Create your file either privately (readable only by your app) using ctx.openFileOutput("Medicine.txt", MODE_PRIVATE) or publicly using new File(Environment.getExternalStorageDirectory(), "Medicine.txt").
To read the private file, use Context.openFileInput(String name).
I want to retrieve file from ftp server, I have also used Apache poi client.retrieveFile() method, but I'm unable to open it which is showing:
excel cannot open file check file extension and file format. check file is not corrupted
Then I used file reader and writer. Below is my code snippet.
public void testFileWriter()
{
try{
FTPFile[] files = client.listFiles("/Ftp1");
for (FTPFile file : files) {
File serverFile = new File("D:/Pondi.xlsx");
if(!serverFile.isFile())
{
serverFile.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(serverFile));
client.enterLocalPassiveMode();
InputStream inputStream = client.retrieveFileStream("/Ftp1/"+ file.getName());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("Created Reader");
while(reader.read()!=-1)
{
String temp = reader.readLine();
System.out.println(temp);
writer.write(temp);
}
writer.flush();
writer.close();
reader.close();
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
Please help me to resolve this crucial issue.
You have to use an API for working with it. You can't read these files like reading normal text files.
JExcel will be good for your need.
Examples are be available here
For copying files make use of this. Reading the file for copying by the method that you used won't work properly.
Hope will be helpful for you.
If you want to read and copy binary data, you must not use reader.readLine(), because there are no lines in a binary file. Therefore, this attempt will most likely fail.
Copy it like this instead:
int fileNo = 0;
for (FTPFile file : files) {
File serverFile = new File("D:/Pondi_" + fileNo + ".xlsx");
...
InputStream in = client.retrieveFileStream("/Ftp1/"+ file.getName());
OutputStream out = new FileOutputStream(serverFile);
// read and copy binary data
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
fileNo++;
}
Beside that, consider giving your files a different name that D:/Pondi.xlsx, because otherwise the file gets overridden again and again in the loop. I did this with fileNo.
I know this question might sound really basic for most of you. I need to download a large file from server. The first line of this file contains a time tag. I want to download entire file only if my time tag mismatches to that of file. For this I'm using the given code. However, I'm not sure if this actually prevents file from uselessly downloading entire file.
Please help me out !
public String downloadString(String url,String myTime)
{
try {
URL url1 = new URL(url);
URLConnection tc = url1.openConnection();
tc.setConnectTimeout(timeout);
tc.setReadTimeout(timeout);
BufferedReader br = new BufferedReader(new InputStreamReader(tc.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
if(line.contains(myTime))
{
Log.d("TIME CHECK", "Article already updated");
break;
}
sb.append(line+"\n");
}
br.close();
return sb.toString();
}
catch(Exception e)
{
Log.d("Error","In JSON downloading");
}
return null;
}
No, there is no easy way to control exactly to the last byte what will be downloaded. Even at the Java level you are involving a BufferedReader, which will obviously download more than you ask for, buffering it. There are other buffers as well, including at the OS level, which you cannot control. The proper technique to download only new files with HTTP is to use the IfModifiedSince header.
Your code won't download the whole file but as the BufferedReader has a default buffer size of 8192 you will read at least that many characters.
You can go byte-by-byte or chunk-by-chunk if it is the size
BufferedInputStream in = new BufferedInputStream(url).openStream())
byte data[] = new byte[1024];
int count;
while((count = in.read(data,0,1024)) != -1)
{
out.write(data, 0, count);
}
Check this question please
How to download and save a file from Internet using Java?
Is there a way to prepend a line to the File in Java, without creating a temporary file, and writing the needed content to it?
No, there is no way to do that SAFELY in Java. (Or AFAIK, any other programming language.)
No filesystem implementation in any mainstream operating system supports this kind of thing, and you won't find this feature supported in any mainstream programming languages.
Real world file systems are implemented on devices that store data as fixed sized "blocks". It is not possible to implement a file system model where you can insert bytes into the middle of a file without significantly slowing down file I/O, wasting disk space or both.
The solutions that involve an in-place rewrite of the file are inherently unsafe. If your application is killed or the power dies in the middle of the prepend / rewrite process, you are likely to lose data. I would NOT recommend using that approach in practice.
Use a temporary file and renaming. It is safer.
There is a way, it involves rewriting the whole file though (but no temporary file). As others mentioned, no file system supports prepending content to a file. Here is some sample code that uses a RandomAccessFile to write and read content while keeping some content buffered in memory:
public static void main(final String args[]) throws Exception {
File f = File.createTempFile(Main.class.getName(), "tmp");
f.deleteOnExit();
System.out.println(f.getPath());
// put some dummy content into our file
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
for (int i = 0; i < 1000; i++) {
w.write(UUID.randomUUID().toString());
w.write('\n');
}
w.flush();
w.close();
// append "some uuids" to our file
int bufLength = 4096;
byte[] appendBuf = "some uuids\n".getBytes();
byte[] writeBuf = appendBuf;
byte[] readBuf = new byte[bufLength];
int writeBytes = writeBuf.length;
RandomAccessFile rw = new RandomAccessFile(f, "rw");
int read = 0;
int write = 0;
while (true) {
// seek to read position and read content into read buffer
rw.seek(read);
int bytesRead = rw.read(readBuf, 0, readBuf.length);
// seek to write position and write content from write buffer
rw.seek(write);
rw.write(writeBuf, 0, writeBytes);
// no bytes read - end of file reached
if (bytesRead < 0) {
// end of
break;
}
// update seek positions for write and read
read += bytesRead;
write += writeBytes;
writeBytes = bytesRead;
// reuse buffer, create new one to replace (short) append buf
byte[] nextWrite = writeBuf == appendBuf ? new byte[bufLength] : writeBuf;
writeBuf = readBuf;
readBuf = nextWrite;
};
rw.close();
// now show the content of our file
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
You could store the file content in a String and prepend the desired line by using a StringBuilder-Object. You just have to put the desired line first and then append the file-content-String.
No extra temporary file needed.
No. There are no "intra-file shift" operations, only read and write of discrete sizes.
It would be possible to do so by reading a chunk of the file of equal length to what you want to prepend, writing the new content in place of it, reading the later chunk and replacing it with what you read before, and so on, rippling down the to the end of the file.
However, don't do that, because if anything stops (out-of-memory, power outage, rogue thread calling System.exit) in the middle of that process, data will be lost. Use the temporary file instead.
private static void addPreAppnedText(File fileName) {
FileOutputStream fileOutputStream =null;
BufferedReader br = null;
FileReader fr = null;
String newFileName = fileName.getAbsolutePath() + "#";
try {
fileOutputStream = new FileOutputStream(newFileName);
fileOutputStream.write("preappendTextDataHere".getBytes());
fr = new FileReader(fileName);
br = new BufferedReader(fr);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
fileOutputStream.write(("\n"+sCurrentLine).getBytes());
}
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
if (br != null)
br.close();
if (fr != null)
fr.close();
new File(newFileName).renameTo(new File(newFileName.replace("#", "")));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}