2013-07-19 3 views
1

У меня есть два процесса Java: Processor и Simulator. Simulator записывает File X предписанную запись данных (10 строк текста) каждые 5 секунд. Processor постоянно читает этот файл, ожидая токенов, чтобы указать действительную запись. Код этого (с некоторыми заменами для имен файлов):Чтение и запись файлов «одновременно» в разных процессах

В Simulator, каждые 5s:

FileWriter fileWriter = new FileWriter(DATA_FILE, true); 
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); 
bufferedWriter.write(DATA); 
bufferedWriter.close(); 

В Processor, постоянно:

mScanner = new Scanner(new BufferedReader(
     new FileReader(DATA_FILE))); 
mScanner.useLocale(Locale.UK); 

while (true) {    
    while (mScanner.hasNextLine()) { 
    // Parse the data bundle. 
    if (parseDataBundle()) { 
      ... 
     } 
    } 
} 

Ранее Processor зацепила к InputStream и не было проблем с использованием Scanner (сконфигурировано соответствующим образом) для чтения данных по мере их поступления.

Здесь я могу видеть, что данные записываются правильно , когда он сгенерирован, обновив файл в Блокноте. Но при использовании файла, а не InputStream, линия if (parseDataBundle()) { никогда не будет достигнута.

Что я делаю неправильно? Processor, похоже, содержит файл ресурсов, поскольку я не могу удалить его во время его работы. Моя кишка думает, что это, вероятно, связано с неправильным использованием параллелизма.

ответ

2

Я бы сказал, что это неправильное использование файлов. Файлы не предназначены для обмена сообщениями. Как только вы достигли конца файла, вот и все. Единственный способ избежать этого - убедиться, что вы только читаете, когда знаете, что есть больше данных (путем проверки длины). Это сложнее при использовании текста.

Вы можете использовать файлы с текстом, но это сложно. У вас должен быть один поток, опросив размер файла, и когда он изменится, прочитайте только добавленные байты (и не более). Это можно записать в трубу. Ваш поток чтения может считывать из канала с помощью InputStreamReader и BufferedReader.


Чтобы изменить интервал опроса можно использовать эскалацию интервал ожидания как

long lastSize = 
int maxSleep = 5000, sleep = 200; 
while(!Thread.currentThread().isInterrupted()) { 
    long size = file.length(); 
    if (size > lastSize) { 
     copyData(size - lastSize); 
     lastSize = size; 
     sleep = 200; 
    } else { 
     Thread.sleep(sleep); 
     sleep += 200; 
     if (sleep > maxSleep) 
      sleep = maxSleep; 
} 

Преимущество этого подхода заключается в том, что время он спит, адаптируя к скорости он получает сообщения.

+0

Я могу заставить симулятор писать что угодно, но ему, безусловно, нужно писать текст таким образом, так как это делает его эмуляция. Реальное оборудование использует RS232 для связи, поэтому я мог бы закрепить на этом симулятор и использовать InputStream, как и раньше, но я бы предпочел сделать это с нулевым оборудованием. Как бы использовать Socket здесь? –

+1

Отправка сообщений через сокеты намного проще для чтения. Вы можете использовать файлы с текстом, но это сложно. У вас должен быть один поток, опросив размер файла, и когда он изменится, прочитайте только добавленные байты (и не более). Это можно записать в трубу. Ваш поток чтения может считывать из канала с помощью InputStreamReader и BufferedReader. –

+0

Хорошо, спасибо. Я посмотрю на это - похоже, это будет аккуратное решение. –

0

Java NIO обеспечивает поддержку блокировки файлов. В зависимости от базовой ОС вы можете получить эксклюзивную блокировку файла при записи и освобождении блокировки после завершения записи. Другой процесс может попытаться получить блокировку, если она появится, прочитать файл и освободить его. Опрос, пока вы не приобретете замок. Надеюсь, вы получите эту идею. Посмотрите на FileChannel#lock() API.

Смежные вопросы