I'm trying to access a shared file from my app, e.g //172.24.9.13/c/2012xp.mdb
By doing:
new File("//172.24.9.13/c/2012xp.mdb");
it doesn't work.
I found the jCIFS library, and creating
new SmbFile("//172.24.9.13/c/2012xp.mdb");
it works, but the problem is that I need a java.io.File.
I have also seen that there is no way to mount smb's on android devices without rooting them.
Is there a way to get a java.io.File instance of my shared file?
I don't think you'll be able to read it as java.io.File because it's not one.
If you absolutely need a java.io.File you'll probably have to call smbFile.getInputStream() and copy to a local file, than you use that local file.
Considering it's a .mdb file you're probably wanting to read data from the DataBase, and it might be a huge file and you don't want to copy it over. On that situation, your only option is to setup a server, with an api that replies in JSON and your app will send GET requests to it.
try this code. i'm not sure about .mdb file format. but this works for PDF files.
first create a SmbFileInputStream using your smb file.
in = new SmbFileInputStream(sFile);
Then create a output file in the device storage (SD card)
outputfile = new File(dir, "todevice.pdf");
Then create a FileOutputStream (java IO)
out = new FileOutputStream(outputfile);
Then read input(SMB) and write it in to the output(IO)
while ((read = in.read(buffer)) > 0 )
{
try {
out.write(buffer, 0, read);
} catch (IOException e) {
}
}
Now u have a file on your sd card
Related
This problem I am facing in title is very similar to this question previously raised here (Azure storage: Uploaded files with size zero bytes), but it was for .NET and the context for my Java scenario is that I am uploading small-size CSV files on a daily basis (about less than 5 Kb per file). In addition the API code uses the latest version of Azure API that I am using in contrast against the 2010 used by the other question.
I couldn't figure out where have I missed out, but the other alternative is to do it in File Storage, but of course the blob approach was recommended by a few of my peers.
So far, I have mostly based my code on uploading a file as a block of blob on the sample that was shown in the Azure Samples git [page] (https://github.com/Azure-Samples/storage-blob-java-getting-started/blob/master/src/BlobBasics.java). I have already done the container setup and file renaming steps, which isn't a problem, but after uploading, the size of the file at the blob storage container on my Azure domain shows 0 bytes.
I've tried alternating in converting the file into FileInputStream and upload it as a stream but it still produces the same manner.
fileName=event.getFilename(); //fileName is e.g eod1234.csv
String tempdir = System.getProperty("java.io.tmpdir");
file= new File(tempdir+File.separator+fileName); //
try {
PipedOutputStream pos = new PipedOutputStream();
stream= new PipedInputStream(pos);
buffer = new byte[stream.available()];
stream.read(buffer);
FileInputStream fils = new FileInputStream(file);
int content = 0;
while((content = fils.read()) != -1){
System.out.println((char)content);
}
//Outputstream was written as a test previously but didn't work
OutputStream outStream = new FileOutputStream(file);
outStream.write(buffer);
outStream.close();
// container name is "testing1"
CloudBlockBlob blob = container.getBlockBlobReference(fileName);
if(fileName.length() > 0){
blob.upload(fils,file.length()); //this is testing with fileInputStream
blob.uploadFromFile(fileName); //preferred, just upload from file
}
}
There are no error messages shown, just we know that the file touches the blob storage and shows a size 0 bytes. It's a one-way process by only uploading CSV-format files. At the blob container, it should be showing those uploaded files a size of 1-5 KBs each.
Instead of blob.uploadFromFile(fileName); you should use blob.uploadFromFile(file.getAbsolutePath()); because uploadFromFile method requires absolute path. And you don't need the blob.upload(fils,file.length());.
Refer to Microsoft Docs: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-java#upload-blobs-to-the-container
The Azure team replied to a same query I've put on mail and I have confirmed that the problem was not on the API, but due to the Upload component in Vaadin which has a different behavior than usual (https://vaadin.com/blog/uploads-and-downloads-inputs-and-outputs). Either the CloudBlockBlob or the BlobContainerUrl approach works.
The out-of-the-box Upload component requires manual implementation of the FileOutputStream to a temporary object unlike the usual servlet object that is seen everywhere. Since there was limited time, I used one of their addons, EasyUpload, because it had Viritin UploadFileHandler incorporated into it instead of figuring out how to stream the object from scratch. Had there been more time, I would definitely try out the MultiFileUpload addon, which has additional interesting stuff, in my sandbox workspace.
I had this same problem working with .png (copied from multipart files) files I was doing this:
File file = new File(multipartFile.getOriginalFilename());
and the blobs on Azure were 0bytes but when I changed to this:
File file = new File("C://uploads//"+multipartFile.getOriginalFilename());
it started saving the files properly
I was wondering if there is a way to access a file and it's path from my assets folder in android studio? The reason why I need to access the file and its path is because I am working with a method that REQUIRES the String path for a file, and it must access the file from its String path. However, in android studio I haven't found a way to access the file directly from the String value of its path. I decided to use a workaround and simply read the file from an InputStream and write the file to an OutputStream, but the file is about 170MB, and it is too memory intensive to write the File to an OutputStream. It takes my application about 10:00 Minutes to download the file when I implement that strategy. I have searched all over this website and numerous sources to find a solution (books and documentation) but am unable to find a viable solution. Here is an example of my code:
#Override
public Model doInBackground(String... params){
try {
String filePath = context.getFilesDir() + File.separator + "my_turtle.ttl";
File destinationFile = new File(filePath);
FileOutputStream outputStream = new FileOutputStream(destinationFile);
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("sample_3.ttl");
byte[] buffer = new byte[10000000];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
model = ModelFactory.createDefaultModel();
TDBLoader.loadModel(model, filePath, false);//THIS METHOD REQUIRES THE FILE PATH.
MainActivity.presenter.setModel(model);
}catch(FileNotFoundException e){
e.printStackTrace(System.out);
}
catch(IOException e){
e.printStackTrace(System.out);
}
return model;
}
As you can see the TDBLoader.loadModel() method requires a String for the file URI as the second argument, so it would be convenient to have the ability to access the File directly from my assets folder without utilizing an InputStream. The method takes as an argument (Model model, String url, Boolean showProgress). As I mentioned, the current strategy I am using utilizes too much memory and either crashes the Application entirely, or takes 10 minutes to download the file I need. I am using an AsyncTask to perform this operation, but due to the length of time required to perform the task that kind of defeats the purpose of an AsyncTask in this scenario.
What further complicates things is that I have to use an old version of Apache Jena because I am working with Android Studio and the official version of Apache Jena is not compatible with android studio. So I have to use a port that is 8 years old which doesn't have the updated classes that Apache Jena offers. If I could use the RDFParser class I could pass an InputStream, but that class does not exist in the older version of Apache Jena that I must use.
So I am stuck at this point. The method must utilize the String url path of the file in my assets folder, but I don't know how to access this without writing to a custom file from an InputStream, but writing to the file from the InputStream utilizes too much memory and forces the App to crash. If anyone has a solution I will greatly appreciate it.
Here is an example of my code
new byte[10000000] may fail, as you may not have a single contiguous block of memory that big. Plus, you might not have that much heap space to begin with. Use a smaller number, such as 65536.
It takes my application about 10:00 Minutes to download the file when I implement that strategy
The time will vary by hardware. I would not expect it to be that slow on most devices, but it could be on some.
I was wondering if there is a way to access a file and it's path from my assets folder in android studio?
You are running your app on Android. Android Studio is not running on Android. Assets are not files on the Android device. They are entries in the APK file, which is basically a ZIP archive. In effect, your code is unZIPping 170MB of material and writing it out to a file.
If anyone has a solution I will greatly appreciate it.
Work with some people to port over an updated version of Jena that offers reading RDF from an InputStream.
Or switch to some other RDF library.
Or work with the RDF file format directly.
Or use a smaller RDF file, so the copy takes less time.
Or download the RDF file, if you think that will be preferable to copying over the asset.
Or do the asset-to-file copying in a foreground JobIntentService, updating the progress in its associated Notification, so that the user can do other things on their device while you complete the copy.
I was able to upload an expandable file and download it
on my app from google play. Following the o[fficial tutorial][1]
It saved the obb file to /Android/Obb/main.2.myappname.obb
I assumed this obb file would be extracted on assets or raw folder or
something similiar. The obb file was renamed after I zipped about 20 .mp3
files. They are named like so: 1.mp3, 2.mp3 etc.
Is it possible to extract the obb file if not how will I be able to
access the invididual mp3 files, the way I am able to access them from
assets or raw folder. Let's say I want to access 1.mp3 which is present
on the .zip archive that was renamed to main.2.myappname.obb
Thank you.
I'm surprised that no one has chimed in here. You can use the StorageManager to mountObb(), unmountObb(), getMountedObbPath(), and isObbMounted(). After mounting an Obb and calling getMOuntedObbPath, you can use the path returned to do normal reads from it. It acts as a virtual drive. You just cannot write back to it.
Here's the link to the documentation: https://developer.android.com/reference/android/os/storage/StorageManager.html
You can read from the OBB directly via an InputStream using the APK Expansion Zip Library. Documentation:
https://developer.android.com/google/play/expansion-files?hl=ko#ZipLib
Sample code:
try {
String obbFilePath = mContext.getObbDir() + "/" + "main.{package_name}.{version_code}.obb";
ZipResourceFile expansionFile = new ZipResourceFile(obbFilePath);
InputStream inputStream = mExpansionFile.getInputStream("1.mp3");
} catch (Exception e) {
Log.d(TAG, "Exception loading obb: " + e);
}
In place of the last line, since you are streaming a MP3, using MediaPlayer is a better idea.
I am trying to learn how to use the Simple XML Framework as detailed in this thread : Best practices for parsing XML.
I am using the following code :
public class SimpleXMLParserActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
Serializer serializer = new Persister();
Example example = new Example("Example message", 123);
File result = new File("example.xml");
try {
Log.d("Start", "Starting Serializer");
serializer.write(example, result);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Self", "Error");
e.printStackTrace();
}
}
}
I am having a problem understanding the line
File result = new File("example.xml");
1) Does this line create a new file in my app called example.xml ? If so where is this file located.
2) Or does this line look for an existing file called example.xml and then add to it ? If so where should the example.xml file be placed in my app bundle so that it can be found. I do notice at the moment I am getting an error message :
java.io.FileNotFoundException: /example.xml (Read-only file system)
Thank you.
File result = new File("example.xml")
This line will just store the filename "example.xml" in a new File object. There is no check if that file actually exists and it does not try to create it either.
A file without specifying an absolute path (starting with / like new File("/sdcard/example.xml")) is considered to be in the current working directory which I guess is / for Android apps (-> /example.xml (Read-only file system))
I guess serializer.write(example, result); tries to create the actual file for your but fails since you can't write to '/'.
You have to specify a path for that file. There are several places you can store files, e.g.
Context#getFilesDir() will give you a place in your app's home directory (/data/data/your.package/files/) where only you can read / write - without extra permission.
Environment#getExternalStorageDirectory() will give you the general primary storage thing (might be /sdcard/ - but that's very different for devices). To write here you'll need the WRITE_EXTERNAL_STORAGE permission.
there are more places available in Environment that are more specialized. E.g. for media files, downloads, caching, etc.
there is also Context#getExternalFilesDir() for app private (big) files you want to store on the external storage (something like /sdcard/Android/data/your.package/)
to fix your code you could do
File result = new File(Environment.getExternalStorageDirectory(), "example.xml");
Edit: either use the provided mechanisms to get an existing directory (preferred but you are limited to the folders you are supposed to use):
// via File - /data/data/your.package/app_assets/example.xml
File outputFile = new File(getDir("assets", Context.MODE_PRIVATE), "example.xml");
serializer.write(outputFile, result);
// via FileOutputStream - /data/data/your.package/files/example.xml
FileOutputStream outputStream = openFileOutput("example.xml", Context.MODE_PRIVATE);
serializer.write(outputStream, result);
or you may need to create the directories yourself (hackish way to get your app dir but it should work):
File outputFile = new File(new File(getFilesDir().getParentFile(), "assets"), "example.xml");
outputFile.mkdirs();
serializer.write(outputFile, result);
Try to avoid specifying full paths like "/data/data/com.simpletest.test/assets/example.xml" since they might be different on other devices / Android versions. Even the / is not guaranteed to be /. It's safer to use File.separatorChar instead if you have to.
2 solutions to do it cleanly :
use openFileOutput to write a private file in the application private directory (which could be located in the internal memory or the external storage if the app was moved there). See here for a snippet
or use the File constructor to create the File anywhere your app has write access. This is if you want to store the file on the SDCard for example. Instantiating a file doesn't create it on the file system, unless you start writiung to it (with FileOutputStream for example)
I'd recommend approach 1, it's better for users because these files get erased when your app is uninstalled. If the file is large, then using the External Storage is probably better.
What I read on the Android pages, I see it creates a file with that name:
File constructor
I think it writes it to the /data/data/packagname directory
edit: the 'packagename' was not shown in the tekst above. I put it between brackets. :s
Try saving to /sdcard/example.xml.
Im trying to copy a file in java and move it to a new folder. This is the code i HAve been using but I always get this error "(Access is denied) in the specified directory". Is there a way i can fix this or a better way to copy the files? thanks
try{
File f1 = new File(fpath);
File f2 = new File("C:/users/peter/documents/foldertest2/hats");
InputStream in = new FileInputStream(f1);
//For Append the file.
//OutputStream out = new FileOutputStream(f2,true);
//For Overwrite the file.
OutputStream out = new FileOutputStream(f2);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
}
catch(FileNotFoundException ex){
System.out.println(ex.getMessage() + " in the specified directory.");
System.exit(0);
}
catch(IOException e){
System.out.println(e.getMessage());
}
UPDATE:
I checked the folder permissions and they are all open for all users and mine
Apache Commons IO is also another way to go, specifically FileUtils.copyFile(); it handles all the heavy lifting for you.
Use Java 7:
import static java.nio.file.StandardCopyOption.*;
Files.copy(source, target, REPLACE_EXISTING);
http://docs.oracle.com/javase/tutorial/essential/io/copy.html
Is there a way i can fix this or a better way to copy the files?
If you have the option, I would recommend you to go with Java version 7, and use the Path.copyTo method.
Copy the file located by this path to a target location. [...]
Otherwise I would recommend at least using the NIO packages and FileChannels.
Edit ups messed up, second try:
You have to give the FileOutputStream a valid file name, just append the name of your file to the target path C:/users/peter/documents/foldertest2/hats/hat3 with only the folder name it will try to access the folder as if it was a file and fail.
If you get this exception the access is really denied, i.e. you just do not have rights to write to the specified directory or file.
So, first check it. Try for example to create the file in specified directory manually. Do you probably try to create file in somebody else' home directory? Or your java program is running as other user? What about foldertest2? Does it exist and writable? Try to copy your file there.
And the final tip. When you manage to copy the file, I'd recommend you to use IOUtils.copy() (from jacarta commons). I use it a lot. It does almost exactly what you implemented but have to write of code one line only.
Hmm it looks like you are trying to run this on windows, should you not be using \ in your path instead of / ?
As AlexR said check your permissions on the directory you are trying to write to.