Поврежденный файл PDF, декодированный и отправленный через сокет Java-сервера - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть программа, которая декодирует PDF и отправляет его через сокет.Я просмотрел много кода на переполнение стека, но не смог найти что-то, что решает проблему.Клиент Android считывает текст, преобразует его в байт-код и записывает файл в кеш, который должен быть загружен pdfViewer.Любое тестирование в программе просмотра PDF работает так же, как и сообщения, которые передаются клиенту, но когда файл пересылается через сокет, файл PDF поврежден.Файл фактически создан и выдаст ошибку, что pdf пуст, если в него не записано ни одного байта.Я исключил перехват ошибок и другую информацию, потому что остальная часть кода не связана:

Сервер:

File f = new File(PATH_TO_PDF);
FileInputStream is = new FileInputStream(f);
byte[] pdf = new byte[(int)(f.length())];

int a;
int count = 0;
while ((a=is.read())!= -1){
       pdf[count] = (byte)a;
       count++;
       }

is.close();
String result = "";

for (int i = 0; i < pdf.length; i++) {
     returnMessage.append(pdf[i]);
     }

OutputStream os = s.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage + "\n");
System.out.println("Message sent to the client is "+ returnMessage);
bw.flush();

//rest is closing socket stuff


Клиент:

 InputStream is = s.getInputStream();
 InputStreamReader isr = new InputStreamReader(is);
 BufferedReader br = new BufferedReader(isr);
 String message = br.readLine();
 s.close();

 byte[] bytes = message.getBytes();

 File someFile = new File(getCacheDir() + "/file.pdf");
 FileOutputStream fos = new FileOutputStream(someFile);
 fos.write(bytes);
 fos.flush();
 fos.close();

Любая помощь очень ценится!

1 Ответ

0 голосов
/ 04 февраля 2019

Вы используете Writer и Reader классы и текстовые ориентированные методы:

OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage + "\n");

и

InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
byte[] bytes = message.getBytes();

Это означает, что вы обрабатываете данные как текст.Одного этого достаточно, чтобы повредить двоичные данные, например, файлы PDF.

Всякий раз, когда вы обрабатываете двоичные данные как текст, предполагается, что байты данных кодируются в виде текста в соответствии с некоторой кодировкой символов, например Latin-1 или UTF.-8.Но не все последовательности байтов могут быть должным образом преобразованы в текст, существуют последовательности байтов, для которых нет текста, который бы кодировал эти последовательности, в частности, в соответствии с UTF-8.Затем такие байтовые последовательности обычно преобразуются в символ замены , поэтому исходные последовательности теряются при трансляции.Когда строка снова обрабатывается как байтовый массив, вместо этих последовательностей вы получаете код символа заменяющего символа и файл поврежден.

Более того, вы, скорее всего, рано обрежете прочитанные данные.

BufferedReader.readLine() считывает только символы до следующего символа, который можно интерпретировать как разделитель строк.Поскольку байты, представляющие разделители строк в соответствии с базовой кодировкой, могут находиться в произвольных позициях в двоичных файлах, readLine(), скорее всего, даже не прочитал весь (уже поврежденный) PDF-документ.


На основеНа этих подсказках вы изменили свой код, чтобы он не обрабатывал PDF как текст:

Сервер:

File f = new File("Path_to_PDF");
byte[] pdf = new byte [(int)f.length()];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(pdf,0,pdf.length);
OutputStream os = s.getOutputStream();
os.write(pdf, 0, pdf.length);
os.flush();

Клиент:

int FILE_SIZE = 60000000; //just a large size
int current = 0;
byte[] pdf = new byte[FILE_SIZE];
InputStream is = s.getInputStream();
File someFile = new File(getCacheDir() + "/file.pdf");
FileOutputStream fos = new FileOutputStream(someFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = 0;
int b;
while ((b = is.read()) != -1) {
   bos.write(b);
   bytesRead++;
}
bos.flush();
bos.close();
fos.close();

С этими изменениямикод работает для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...