From RS232 to SD writing issue

I'm doing an Arduino project, so that Arduino must store all the information it gets from RS232 to a microSD card.
The code below works correctly, when I send the information myself from the keyboard using Hyperterminal.
But when I use the "Send a TXT file" function in HyperTerminal, Arduino stores only few first characters.
I suppose it can't deal with so much information in such a little time or Arduino goes asynchronic with Hyperterminal.
Please write if I can optimize the code somehow, or how I can deal with this problem. Thanks!

P.s. I'm using Arduino UNO, Arduino Interface Shield and a TTL - RS232 converter.

#include <SdFat.h>
#include <NewSoftSerial.h>

NewSoftSerial mySerial(6, 7);
SdFat sd;

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
byte inbyte;


void setup()  
{
  // set the data rate for the NewSoftSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
  if (!sd.init(SPI_FULL_SPEED)) sd.initErrorHalt();
}

void loop()                     // run over and over again
{
  if (mySerial.available()>0){
    ofstream sdout("no1.txt", ios::out | ios::app);
    inbyte=mySerial.read();
    sdout <<(char)inbyte;
  }
}

On every pass through loop, you open the file, read one character from the serial port, write it to the file, and end.

The sender is continuing to send data as fast as possible. Eventually (very quickly, actually) the serial buffer fills up, and no more data can be accepted. By the time there is room in the buffer, the sender has finished sending all the data that the Arduino discarded.

There are a number of ways to deal with the problem. The most obvious is to open the file once, then read and store all the data until the EOF arrives. Store that, close the file, and end the while loop that is reading/writing to the SD card.

Even that might not be sufficient, since writing to the card is slower than reading from the serial port (or the sender writing to the serial port). In which case, you will need to implement handshaking. THe sender sends some number of bytes, and then waits for the receiver to ask for more.

Whether that is possible with your sender, I do not know.

If not, you will need to slow the serial speed down to the point where sending a character takes as long (or longer) as writing to the SD card. Or, you will need to find/develop a different sender. Or, simply put the SD card in the PC, write to it, then move the SD card back to the Arduino.

Thanks for such a quick reply. In my case lowering the speed or making the sender to wait unti the receiver asks for some more bytes is impossible. In fact, the sender is a snack machine that sends its statistics.

I wish you could help me with realization of the code that opens the file once, then reads and stores all the data. The problem is when I open the stream in void setup() , the sdout stream in void loop() gives an error like "sdout was not declared in that scope".

As far as I know, the writing speed of the microSD is few times faster than the speed of 9600 baud (I made a test of the microSD card). I thing the only problem is that it wastes a lot of time opening the stream every time it gets a byte to read. Please write how I can open the stream only once. By the way, the operation of EOF is already done, I posted the part of the scetch that refers to writing on SD only.

Psuedo code:
#define EOF someValue
void loop()
{
if(serial available)
{
open the file
byte inByte = 0;
while(serial available and inByte != EOF)
{
read a character, storing it in inByte
write to file
}
close the file
}
]

Thank you so much! That worked for me. Almost. Now it looks something like this:

#include <SdFat.h>
#include <NewSoftSerial.h>

NewSoftSerial mySerial(6, 7);
SdFat sd;

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
byte inbyte;


void setup()  
{
  Serial.begin(9600);
  Serial.println("Goodnight moon!");
  // set the data rate for the NewSoftSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
  if (!sd.init(SPI_FULL_SPEED)) sd.initErrorHalt();
}

void loop()                     // run over and over again
{
    if (mySerial.available()>0){
        ofstream sdout("no3.txt", ios::out | ios::app);
        while(mySerial.available()>0){
            inbyte=mySerial.read();
            sdout <<(char)inbyte;
        }    
    }
}

But as you said, there are some bytes lost, approximately every fourth or fifth character is lost... I checked it also on the rate 4800 baud and it works almost perfectly. It loses only 2 characters in 5000 of them because it deals with all available bytes to read and goes out of the while, again it opens the stream and looses here 1 character (that happens twice a file).

Returning to the task, I have to read on the rate 9600baud. The speed of the microSD card: Write 182.39 KB/sec (on Arduino). So is there any way to improve this situation?

Up. Why is not it writing on the full speed? 1kb/sec is not the limit.

void loop()                     // run over and over again
{
    if (mySerial.available()>0){
        ofstream sdout("no3.txt", ios::out | ios::app);
        while(mySerial.available()>0){
            inbyte=mySerial.read();
            sdout <<(char)inbyte;
        }    
    }
}

You are still opening and closing the file many times before the whole file is received.

I suggested:

while(serial available and inByte != EOF)

You didn't implement the highlighted part.

I know, in my final program i have it, but it still can't deal with all characters.