Android read file from assets by FileInputStream [duplicate] - android

This question already has answers here:
How to get FileInputStream to File in assets folder
(2 answers)
Closed 7 years ago.
I know that I can read files from assets using AssetManager, like here
AssetManager assetManager = getAssets();
InputStream is = assetManager.open(filename)
but open() method returns InputStream. So what I should do when I need to work with FileInputStream not with it superclass. Is there a way to get FileInputStream instance by InputStream instance?

No, there is not a way to convert an arbitrary InputStream back to a FileInputStream, as the data source may be of a different nature - something other than a literal File.
Assets are not files on the device, but rather particular chunks of the zip file which is your .apk. The Asset APIs give you access that is file-like in many ways (particularly with regard to input streams), but does not ultimately wrap an individual java.io.File, but rather an engine for extracting data directly from the .apk

In that case you can create a StringBuilder and read whole content of text file in it something like this
StringBuilder buf=new StringBuilder();
InputStream is=getAssets().open(filename);
BufferedReader in= new BufferedReader(new InputStreamReader(is, "UTF-8"));
String str;
while ((str=in.readLine()) != null) {
buf.append(str);
}
in.close();
Note: Things differ based on the file type you try to access; as Chris Stratton wrote as the data source may be of a different nature.

Related

Get an InputStream from a ZipEntry from a ZipInputStream from a DocumentFile

This is for an experimental Android project done in Java. What I need is to read a ZIP file from an external card (as fast as possible, if possible) and return the InputStream corresponding to an entry each time it is needed by an OSMDroid custom tiles provider.
I can do this pretty easily when serving a ZIP from the primary (or whatever it's called within their mangled filesystem) disk but when trying to read from an external card, the only option in newer versions of Android is to use their shiny SAF.
When the path is not a relative one but a URI to an external card, I use a DocumentFile to retrieve the ZIP's InputStream (apparently, the only way to do it).
DocumentFile file = DocumentFile.fromSingleUri(this, uri);
ContentResolver contentResolver = getContentResolver();
InputStream inStream = contentResolver.openInputStream(file.getUri());
Question 1:
What would be amazing at this point, where using DocumentFile already took its toll on performance due to how slower it is than the good ol File, is to be able to have that inStream converted into a ZipFile. Or somehow directly get a ZipFile from DocumentFile. Is that possible? Maybe get a File from DocumentFile then a ZipFile from that?
I didn't find any solution so I went on with the InputStream, which I converted to a ZipInputStream. The problem in my code is that I can only run through it once, when what I need is to do it every time a file's stream from the Zip is needed.
public class MyZipFileArchive implements IArchiveFile {
protected static ZipInputStream mZipInputStream;
}
public void init(InputStream inStream) {
mZipInputStream = new ZipInputStream(inStream);
}
public InputStream getInputStream(ITileSource pTileSource, long pMapTileIndex) {
final String path = pTileSource.getTileRelativeFilenameString(pMapTileIndex);
ZipEntry entry = null;
while ((entry = mZipInputStream.getNextEntry()) != null) {
if (path.equals(entry.getName())) {
return mZipInputStream;
}
}
return null;
}
Question 2:
The first time the getInputStream is called it returns what it finds but now the stream is at its end and the second time it does it, null is returned.
So, I need a way to either reset the stream, if possible, each time the function is called, or use another approach. I tried storing each ZipEntry into a List at the beginning, then loop through it. It doesn't work. Also, I did not find a way to convert ZipEntry into the InputStream required to be returned.
How would you tackle this? Basically, I need to use DocumentFile and I need to get a ZipFile from it or some fast way to find its entries.

Where to put a file in android so it can be opened? [duplicate]

This question already has answers here:
How do I read the file content from the Internal storage - Android App
(6 answers)
Closed 6 years ago.
I want to open a file in android using the following code:
FileInputStream fis = openFileInput("examplelist.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
but where to put the file examplelist.txt? I found some contradicting sources, like this and this? How to do it correctly?
Update:
I want to be able to replace this file at anytime after the app has been installed. So this file is NOT part of the source code or anything. It contains dynamical data...
I would have used a simple 'File Selector', so the user can navigate to the file anywhere on the android phone, but this looks terribly complicated and cumbersome. So, for now, I just want to open a file I can put somewhere on the phone in the most possible simple manner...
In order to be able to access a file, you should place it in /app/src/main/assets/examplelist.txt. You can access this directory in the Project explorer in Android Studio.
To open the file from java code, you can create an InputStream object by calling getAssets().open("examplelist.txt")
One possible way to solve this problem is the following:
You put the file in the kind-of-root folder, which might have the following path: /storage/emulated/0 (this is the location you can see when you connect the device e.g. to Linux and open it in the file explorer).
You can open the content of the file using the following code:
String path = Environment.getExternalStorageDirectory().toString();
Log.d("Files", "Path: " + path);
String joinedPath = new File(path, "examplelist.txt").toString();
try {
FileInputStream fis =new FileInputStream(new File(joinedPath));
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
Log.d("Text", sb.toString());
} catch (IOException e) {
Toast.makeText(getBaseContext(), "File does not exist", Toast.LENGTH_LONG).show();
}
VERY IMPORTANT, and which I forget EVERY single time: You have to set permission to the app to access the storage. You have to put the permission tag in the AndroidMainfest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
...
but where to put the file examplelist.txt?
Your app would create the file itself. openFileInput() is part of internal storage, to which ordinary users have no access.
I would have used a simple 'File Selector', so the user can navigate to the file anywhere on the android phone, but this looks terribly complicated and cumbersome.
Step #1: Call startActivityForResult() with an ACTION_OPEN_DOCUMENT or ACTION_GET_CONTENT Intent (the former is for Android 4.4+)
Step #2: In onActivityResult(), if you get RESULT_OK as a result, get the Uri to the user's chosen content via getData() on the Intent passed into onActivityResult()
Step #3: Call openInputStream() on a ContentResolver to get an InputStream to use for reading the content
It's about 10-15 lines of code over what you have in your question, plus the code that your question needs but does not show (e.g., background thread for I/O).
Or, use a file chooser library.
I just want to open a file I can put somewhere on the phone in the most possible simple manner...
Use external storage, such as getExternalFilesDir().

Android write PDF file whith itextpdf pt-BR language

I need write PDF File, and I use this sample(http://www.vogella.com/tutorials/JavaPDF/article.html) with this version "itextpdf-5.4.1.jar".
This create the PDF file, but when the word has "você" write this "você".
I find this code but has not work:
Document document;
...
...
document.addLanguage("pt-BR");
How set encoding or language to Brasil?
Thanks!
Take a look at my answer to Divide page in 2 parts so we can fill each with different source (this is year another question answered in The Best iText Questions on StackOverflow). In this example, we read a series of text files that are stored in UTF-8. To achieve this, we use this method:
public Phrase createPhrase(String path) throws IOException {
Phrase p = new Phrase();
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(path), "UTF8"));
String str;
while ((str = in.readLine()) != null) {
p.add(str);
}
in.close();
return p;
}
If you remove the "UTF8" and if you read that text as if it were ASCII, then you'd get the same behavior you are describing in your question: each byte would be treated as a single character whereas you have characters that require two bytes.
This is not really an iText question. This is a pure encoding question.

How do I store files on an android phone?

When creating an Android application, I have some files that needs to be stored on the android itself.
How do I do this?
If you have local files, like some error tones, some openning video.. then place it in you assets folder of your project.
If you have dynamic data need to download at run time then use this guide.
Best place for generic files would be the assets folder.
You can access files through the AssetManager, which you can get with Activity.getAssets() for example.
Here is an example how you could access a text file:
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(getAssets().open("sometextfile.txt")));
// do stuff with br
} catch (IOException e) {
e.printStackTrace();
}
For more information on AssetManager read the Java Doc. Oh and yes, you can create folders in assets.
If you want to keep some files like readme.txt or even music files, you can use the raw folder inside of res folder. So create a folder named raw inside of res folder.
Inside of raw folder, let us assume that there is a file named readme.txt, assuming that the Activity class is called MyActivity.
Now, you can read the contents of a file into a String as shown below:
StringBuilder strContents = new StringBuilder();
String thisLine;
InputStream is = MyActivity.this.getResources().openRawResource(R.raw.readme);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
while ((thisLine = br.readLine()) != null) { // while loop begins here
strContents.append(thisLine);
}
br.close();
//Now you have the data in strContents
Alternately, assets is also one such folder that you can use since the raw folder contains the file as is without any optimization, zipping done by Android.
So create an assets folder in your Project root folder and place your files there e.g. myfile.
Now, you can get an instance of the file InputStream as given below:
InputStream is = getBaseContext().getAssets().open("mydb");

Android - reading a text file from Assets seems to include a LOT of junk before/after the actual data?

I package a text file with my Android App (in Assets) which I read within the App itself.
To avoid this file being compressed, it's named 'mytestfile.mp3' and until recently, that worked just fine.
In one of the recent SDK/ADT changes, it seems something 'odd' is happening when reading from Assets and I'm open to ideas as to what it is...
I use code something like this
AssetFileDescriptor descriptor = getAssets().openFd("mytextfile.mp3");
BufferedReader f = new BufferedReader(new FileReader(descriptor.getFileDescriptor()));
String line = f.readLine();
while (line != null) {
// do stuff
Log.d("TAG",line);
}
What I'm now seeing from the Log is rather odd - if the file contained something like this
Fred
Barney
Wilma
I'm seeing huge amounts of nonsense like this in the log
��ߴ�!�c�W���6�f����m�>ߩ���'�����6�#6���l0��mp�
followed - eventually by my text content
Fred
Barney
Wilma
followed by another metric tonne of gibberish - some of which looks like this
����������4�u?'����������������������������������������res/drawable-mdpi/icon.pngPK��������|v?,������������'�����������������������������res/layout-land/dialog_color_picker.xmlPK��������|v?1�!�����t2�������������������������������classes.dexPK��������|v?թVڝ����5���������������������������������META-INF/MANIFEST.MFPK��������|v?�v������j���������������������������������META-INF/CERT.SFPK��������|v?W7#�]�������������������������������������META-INF/CERT.RSAPK������������������������
As you can see, that appears to be raw binary content from the APK (and nothing to do with the text file)??
Is this a recent packaging issue or am I missing something? I'm using ADT15 but I've not tried the recent upgrade just yet!?
p.s. I've upgraded to the latest SDK/ADT and this problem persists - obviously I'd like to escalate it with whoever is at fault (no idea if the problem is Eclipse/ADT/ANT or Android centered) and so I'll start a bounty for ideas...
This is because AssetFileDescriptor.getFileDescriptor() is for your .apk and not the mytextfile.mp3 file inside the .apk. To work with AssetFileDescriptor you need to take e.g. AssetFileDescriptor.getStartOffset() into account as well, which is the offset to the actual file i.e. mytextfile.mp3 in your case.
But there's an easy solution to your problem. Use AssetManager.open(String) instead, which will give you an InputStream to the mytextfile.mp3 file. Like this:
InputStream inputStream = getAssets().open("mytextfile.mp3");
BufferedReader f = new BufferedReader(new InputStreamReader(inputStream));
// ...
Eclipse/ADT occasionally gets the resources corrupted. Try doing a project clean and rebuild to see if that fixes it.
I had the same problem with my app. Try using Apache Commons IO's FileUtils.
This adds another 100kb to your apk, but make File handling much easier.
And if you store the file as myfile.txt instead of .mp3, does it give the same output?
And did you create the file with a Windows or Linux/Unix System? (And with what application?)
/edit: This works for me:
AssetManager am = this.getAssets();
InputStream is = am.open("mytextfile.mp3");
InputStreamReader inputStreamReader = new InputStreamReader(is);
BufferedReader f = new BufferedReader(inputStreamReader);
String line = f.readLine();
while (line != null) {
// do stuff
Log.d("TAG", line);
line = f.readLine();
}

Categories

Resources