-1

I'm writing this notepad app where the user types in what they want into an EditText, it will write that to a file, and then later they can read it in a TextView.

Here is my XML code for the EditText I'm using:

<EditText
    android:id="@+id/txtWrite"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/btnLogOut"
    android:layout_marginTop="42dp"
    android:layout_toLeftOf="@+id/btnAppendd"
    android:ems="5"
    android:imeOptions="flagNoExtractUi"
    android:inputType="textMultiLine"
    android:maxLength="2147483646" />

The max length line was my attempt to fix it, seeing as I thought that would be plenty for the user to input. However, it doesn't work.

When I display the length of the file, it says that it is 1024, which makes sense, considering how I input data from my files:

try {
    char[] inputBuffer = new char[1024];
    FileInputStream fIn = openFileInput("txt");
    InputStreamReader isr = new InputStreamReader(fIn);
    isr.read(inputBuffer);
    String data = new String(inputBuffer);
    isr.close(); fIn.close();
    display.setText(data + '\n' + '\n' + data.length()); // data + 1024
}catch(Exception e){}

That is how I input all of my files (Googled), and so I assume the new char[1024] is the reason the max length of the file can only be 1024.

Does anyone know another way of inputting files with limitless length? I don't even know why that has to be new char[1024].

Here is how I write to files, which is nice because it's short code:

FileOutputStream fos = openFileOutput("txt", Context.MODE_PRIVATE);
fos.write(...);
fos.close();

Here is my full write method:

public void write()
{
    Button write = (Button)findViewById(R.id.btnWrite);
    write.setOnClickListener (new View.OnClickListener()
    {
        public void onClick(View v)
        {
            EditText writeText = (EditText)findViewById(R.id.txtWrite);
            try {
                FileOutputStream fos = openFileOutput("txt", Context.MODE_PRIVATE);
                fos.write(writeText.getText().toString().getBytes());
                fos.close();
            } catch(Exception e) {}
        }
    });
}
Michael Yaworski
  • 13,410
  • 19
  • 69
  • 97
  • Why don't you just change this size, I doublt it will not work, put something like 5120 for example. – g00dy Aug 01 '13 at 13:23
  • 1
    I'm hoping for a way to make it as large as possible because I don't want to just put in an arbitrary number. 2147483646 doesn't work. – Michael Yaworski Aug 01 '13 at 13:25
  • 1
    @g00dy That would use a lot more memory than necessary and you still can't read anything above that amount. – user1132959 Aug 01 '13 at 13:27
  • @mikeyaworski - with the current implementation, this isn't possible, you're reading 1024 at a time, you can't read "unspeficied" length chars at a time. – g00dy Aug 01 '13 at 13:34
  • Maybe you can count the characters in the file you're opening before the actual opening and set the char array accordingly (http://www.javamex.com/tutorials/io/character_stream_reader.shtml): `public int countASCIILetters(File f) throws IOException { Reader r = new BufferedReader(new InputStreamReader( new FileInputStream(f), "US-ASCII")); try { int count = 0; int intch; while ((intch = r.read()) != -1) { int ch = (char) intch; if (Character.isLetter(ch)) { count++; } } return count; } finally { r.close(); } }` -like that? – g00dy Aug 01 '13 at 13:40
  • 1
    @g00dy doesn't work. the `return` `int` from the method is 910, so it only reads the first 910 chars. – Michael Yaworski Aug 01 '13 at 14:10

2 Answers2

5

Replace this:

char[] inputBuffer = new char[1024];
FileInputStream fIn = openFileInput("txt");
InputStreamReader isr = new InputStreamReader(fIn);
isr.read(inputBuffer);
String data = new String(inputBuffer);

With this:

FileInputStream fIn = openFileInput("txt");
InputStreamReader isr = new InputStreamReader(fIn);
StringBuffer fileContent = new StringBuffer("");

char[] buffer = new char[1024];
int len;
while ((len = isr.read(buffer, 0, 1024)) != -1) {
    fileContent.append(new String(buffer, 0, len));
}

String data = fileContent.toString();
//be sure to call isr.close() and fIn.close()

Borrowed in part from here

Community
  • 1
  • 1
user1132959
  • 978
  • 8
  • 16
  • Basically, you (@Mike) were only reading that buffer full once. You need to have a loop and keep reading the buffer until you've read the whole file. – chrylis -cautiouslyoptimistic- Aug 01 '13 at 13:26
  • ^ that makes a lot of sense (not sarcastic) – Michael Yaworski Aug 01 '13 at 13:27
  • @mikeyaworski How big is the file? – user1132959 Aug 01 '13 at 13:42
  • @mikeyaworski That may be all that you have in the file is 2048. Verify the file size and that your write code is correct(if testing against that) – user1132959 Aug 01 '13 at 13:49
  • @mikeyaworski Can you post your full write code in your question? You should really use a file browser or something to check the file size. – user1132959 Aug 01 '13 at 13:54
  • It can't be my `writing` because when I switch the `char[1024]` to `char[5120]`, just as a test, it does display my entire file. I didn't even write the file again, I just changed the size of the `char` and read it again and got the full thing. The problem with writing 5120 is that I can't get anything more than that. But I will post my full write method anyways. – Michael Yaworski Aug 01 '13 at 14:03
  • 1
    There's a potentially serious bug in this code. You're reading 1024 bytes at a time and assuming they can be converted to a string using the default character set, but the default character set (on Android) is UTF8, which is a variable-length encoding. If the 1024th byte of a file is the start of a two-byte character (or the first or second byte of a three-byte character, or so on) this will cause the character to be replaced with a marker character that indicates an encoding error. Then the next buffer start will be out of sequence, so some characters at the start of that will be lost too. – Jules Aug 01 '13 at 15:26
  • 1
    To fix the above bug, I'd use the InputStreamReader as the original questioner was doing, and create the string from a char[] rather than the byte[] used here. This shifts that (actually surprisingly difficult) task of working out where you can stop reading onto the system rather than trying to do it yourself. – Jules Aug 01 '13 at 15:30
1

Your code only works if there are 1024 or less characters, meaning that it does not work properly. The idea behind

char[] inputBuffer = new char[1024];

is that you read into the inputBuffer by 1024-sized chunks, you do this until the read functions returns -1 (EOF is reached).

Uku Loskit
  • 40,868
  • 9
  • 92
  • 93