Я пытаюсь создать приложение «виртуального принтера» на C#, которое получает задания печати по сети, анализирует необработанные данные печати для определенной информации и затем сохраняет документ в базу данных. Измененная версия следующего класса работает для заданий постскриптума печати (он сохраняет входящие данные в действительный .prn-файл, точно так же, как если бы принтер был настроен для печати на порт «FILE:».) Когда я пытаюсь выполнить захват. Документы XPS от Microsoft XPS Document Writer, однако, документы не могут быть открыты. Допустимые файлы XPS также должны быть действительными ZIP-файлами, если расширение переименовано, и это тоже не работает. Когда я печатаю тот же документ в порт FILE: а затем в свое приложение, и я сравниваю результаты в Notepad ++, существует 5-символьная разница в длине данных, но она выглядит одинаково (это не простой текст, поэтому трудно смотреть, но первые несколько символов и последние несколько символов выглядят одинаково). Файл с сохраненным «нормальным» способом работает нормально, но файл, созданный моим кодом, не работает.Файлы XPS, полученные через TcpClient, повреждены
В общем, я пытаюсь получить произвольные данные через порт TCP и записать его в файл. Мое решение «близко», но не работает. Я не знаю, что такое кодирование XPS, но я использую ASCII для постскриптума, и я попробовал ASCII и UTF8 для этой версии XPS.
Любая помощь с благодарностью! Вот соответствующая часть моего кода:
class XPSListener
{
private TcpListener tcpListener;
private Thread listenThread;
private string instanceName = "";
private string fileShare = (Settings.Default.SharedPath.Substring(Settings.Default.SharedPath.Length - 1) == @"\") ? Settings.Default.SharedPath : Settings.Default.SharedPath + @"\"; // use SharedPath setting value - append backslash if it isn't already there.
public XPSListener(string initInstanceName, Int32 initPort)
{
this.instanceName = initInstanceName;
this.tcpListener = new TcpListener(IPAddress.Any, initPort);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
try
{
this.tcpListener.Start();
}
catch (Exception e)
{
MessageBox.Show("Socket Error 1 - " + e.StackTrace);
}
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(AcceptXPSData));
clientThread.Start(client);
}
}
private void AcceptXPSData(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
string tempFilePath = fileShare + "XPStemp_" + instanceName + ".oxps";
byte[] message = new byte[65536];
int bytesRead;
string input;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 65536);
Debug.WriteLine("Bytes read: " + bytesRead.ToString());
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
if (instanceName != "DontPrint")
{
Debug.WriteLine(instanceName + " Receiving Data");
//ASCIIEncoding encoder = new ASCIIEncoding();
UTF8Encoding encoder = new UTF8Encoding();
using (FileStream fs = new FileStream(tempFilePath, FileMode.Append, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs))
{
input = encoder.GetString(message, 0, bytesRead);
sw.Write(input);
// first capture this input and write it to an xps file. This file can be converted to PDF at a later time by Ghostscript
// but we will still have access to the temp file for parsing purposes.
}
}
}
}
tcpClient.Close();
// processXPS();
}
@PeterDuniho - Я использую драйвер печати Microsoft XPS Document Writer, просто пытаясь использовать другой порт для отправки результатов в мое приложение, а не запроса сохранения пользователя на жесткий диск. Причиной этого является автоматизация способа имени и хранения файлов. Это будет кошмар, чтобы поддерживать, если файлы теряются каждый раз, когда пользователь называет его неправильно. –
Ну, вы можете использовать двоичный редактор в Visual Studio, чтобы узнать, что такое _precise_ разница между файлами. Я до сих пор не понимаю, как здесь задействован TcpClient, но это не искажает ваши данные, я могу сказать вам многое. Вы не используете его правильно - нет оснований полагать, что ценность данных в целом файла обязательно будет получена в одном вызове 'Read()'. Re encoding: если вы просто записываете данные в файл, не интерпретируйте их вообще ... просто напишите байты прямо в файл. XML (и поэтому XPS) использует UTF8, но, похоже, это не имеет значения. –
Я не обвиняю TCPClient, у меня просто ошибка. Read() находится в цикле - он заполняет буфер, а затем добавляет его в файл, пока не будет больше данных. Отладка будет получена из кода «Bytes Read: 65536 Bytes Read: 65536 Bytes Read: 45888 Bytes Read: 0 "- буфер заполняется дважды, а затем считывает оставшиеся 45888 байт. Это составляет 172,8 kb, что является точным размером файла, который я получаю, когда я «печатаю файл в обычном режиме», но, что интересно, файл, который генерирует моя программа, составляет 310kb, а не 173 kb, как указывает отладка. Двоичный редактор показывает «похожие данные», но много лишнего мусора в моем. –