【问题标题】:Synchronizing Position of FileStream and StreamReaderFileStream 和 StreamReader 的位置同步
【发布时间】:2013-11-05 21:58:13
【问题描述】:

我正在尝试编写一个解析 PDF 文件的程序。从我目前所读到的,PDF 文件是文本数据和二进制数据的组合。

例如,在 PDF 中,有“流”对象以单词 stream(newline) 开头,然后包含必要的二进制数据,然后以单词 endstream(newline) 结尾

这是一个例子:

677 0 obj
<</Length 2821
/Filter /FlateDecode>>
stream
xœ…ZÛnG}÷WLô’, Oú~AÙ 6—AGbKœ5Éf†¦õ™ù£=M™dŸÖX›‡ÄÏô¥êTÕ©j¸yLœ“·¡5J»æfõæÇ_T#M+ðOssÿ懫÷ëë57ÿ}óï›7nÞH[c¼£o~Ø»©Oûñúª„FÝ-yùÆýöv“VP9Ù¯ª5çu*1!´R‡j±iجú48­}k…¶ŒûeìvwC?•71B´2hÁÈ~WBpYeUµØôØÏåÑŒµ­¦Zh¸/!Þ´ÿbȺßNis_Ê‹¯1²u'ÜÕɼmiÞ³óþp†ÞtŸRs×éúª™º~Õ¼»-.Þ\ͧ_¾[\E„VœWùã¾9¬»ù]³JÝØüÖ6«ïMãí¦{:-û¡ë§´MÝþËu³î6÷M¿›‡/ý]7§U»°¾‹²U—S’o3§œ”A›4ÏäZi=h"
Ãëþn]E¨V™(U‘IùÖŽ0wÃ~d2)£¡w;ö»‡©äœÒ­v±:ÿ<”ìϨÍk§ÒÎã'_üaøœÆÝPËhÑ*ªã3áLh«OÞ•q?Œó˜¦òvÙ@ÇX½ŸXë@ó"6·iî·ijº]3Œ«´L_¯^˜þ;ø¶yjºÍ¡{š–ñFtÿyhvÃü¼üÔôÓ´OÍý8l˜¶Ùö»~‡¦w‹!n.Œÿ;!Fö»Õ°¿ƒ7O?5·ûùŸÅï„/˜ü~Wf2©Tk£Ê¡D<m”Ùò%ˆè"½k~® ë4¥n…õ–Qç[‘m«•1Œ\•[ªèZc£bŒ@DW­4¦²âf—÷ëvUzU^ÅW(1pC1&/ÔÍû‘k2åK$QÞ
äØ(Íkžˆj£¸õÂy‘!Ö낚¦qÝ=–V…)àHïø4ìÉ“fµŠ1]NFßjªuÆþa=—©Ti‹_fØï ù·Ü j¯ÉW[ƒ¤Dèïg
\m\®–Õ’Xð©ùØJ!"ƒæy!Ny   †Â0ð°NÄPÛi_3š¶…áÌkF;»ÒºK>˜úy†7©¶À™ZhÆÝ&$ºTÅ$2‹aXGŽeœ°ŒxR2µQ8Ï ¹ƒà)}£ŒUÃ~üÅðšÓœÞvoóJgðÉ™úSÖl‡~.K¢ÖÁã·/§Q.¬s‘÷(‡»Õ?ï×ßQÌzœ]W†ÿXÑÀj©j“—nÁZtå°€ê\mºrÊc7¾]âꂸd¶‰VhíeÐIUýT"] 2F~$À˜9OtzÊT©dÈ2Ä1¬'ʸ51VÊÛÈ0
¹ìÛÇ<mQç«}kJíA·^Cé&íº¢––­UºÚŒ#‹’c=c¨¼ÁЭ
ªÚmÚ?>¦‘ôwÖ­Á™j)ª§·SVTÛÍ\OMÈB>ÊoÉ„LïXm5=¦îÓ“ 犲ÜtÍý>—£,žWý®Û,ê‹Ð?—”«ÿ¤¹JBÀ8í©–h4KÈ1yìHŠIga²œƒJPˆTMBîÐ"ƒ²Í(ÁÙB Z*Ë}jÌ4ì–£¡ÒŸRÎf¡8   ËîÌÔÐ*zÆŒ   Öå¶+÷"¾²)   $ƒZ(¤ª,Z¥(\Ř¯-cyt+Á²¶ ýNÜ0!^
Ò©«\äƒñªÐ©¥ÍæBxuì«Ð1MÍéëÉ*-ꃴwQ¨¿¦ãg«´ÝcZ-vqFÇB›â‹¾8ŒÃîá:+âÝò6Puæþ:²¢ ô    ‰®¤¬ÜÂA`ZgRW4¿R=>{™?áJvº-Q×å‡ó”ŠÐ,ê“0SJe²×(e‰šAµD²2<ƒnÓ]·'1n Y<Šã`tÖ±¨üèP-£hC“S¬AÕã£çnjÍÚæLJa/¤L_汎‰ŠTœD4(­MhwHŸÓdÞ¹„`W*Iˆ(BÁ m—›uR«?G(vÂ}¤ˆoTu$Ú-d%XŸº¨¹Öæø%Ðã0M=„å.êr9Â’qÕ©"!óP—r zHëcoC˜‰„œ#„÷ÕÁO‰aÁÓ…ìœT¸ÈK´?ZC2†CNÇPºÂäüP¢‚D`¢s 3á­2yVp”¢zÉæ1A«¾&‡ú°ŒADSÉ*V¨W a(QÇnt´(^½r=#sÛQ[ ê]uÓðliÀ_\>¾²Yî[…Õ•-™(gÿgœd¹ÍßÁÜ
Dʺß.–!0¼T„¿òñÞ5ó·é¹24ÏÍй½kr@4ȕ۩»œÁPxÆÕòòº˜g^ý   Ø@<‘‚7†q[j†¤ËÁ”‰Ë˜1mÊ W(Ðp‚a]¹›½ÁLÅõãa¿éÆ~~j)k {mý‰‰óë<ª!L)-“¬-1¯‡=ºwÊ*ÐJžÏÆYÄÌš†
ñDIEäddÈj?(g9ç+3°|Šh=¬¯ýÒ}Zê°µ*fÑy–w;¥ñs7÷î9N_Á§ØÒôÛÇaœ»Ý¼LQΩÿ ¦RÊÜ¡¢ÈèñåÄÅç–IjÆUè_´(‘1œ”mÔÎ2æ8q¡'Œ,€µ·Õá§¹Ûf~®êì¤cuƒ‹TnÉÑÐ!T·¨†âÆ"•! 1(Ϫ¾Ÿ*Oc
ÃŽóÐWæW”åN3{    Ý#¦î·¤þX«4qœÍ%dkŒh} Ã…¨Fá(.&r0äyÐK1•¼¯®V•tåp꜅ùD¨UŸy¶¢PÕÀB‚Uó«ã$_[kÇ“|ü…~ÅÞ:äÒªëq#ód\Ô>yÙHç¤cåê³€×¶òȘР—Úü"¦_x…my¦’燤€Ïýfqb®lñ,põ±ÚfÕ‚^.0¦
h¸XgyG˜uGƒw¨[pN0&¿T¥²$)ˆ˜‡-BJ1d»ç'&„¦³º:4±W9„xN°áW¨˜cIVg~Ù)Z…ÜWW‡>"þY§-Oç"®øâüTð‹‹²:}Õùçy»ñõùéliø¦tñˆóõU07»ý=„Éôü<±Âÿ|:—‰»´X'rn¾$E½ S##CèC*(\¡=C¨ÌJÔP‹ÁŠåÒç­¬b&hÆFl;Ö,yêcXÚå_°ÎU—‚¶Û·Äô°1ãhˆî:U[ð¶ŸÖÃ#  4˜6ÆÕ½úo¹…ö_˜\æYëð‡Ü±wÛªˆ…£Ô„ÔlUí0˜ˆ2\DÈ-qå²´[z;W¢xØK_îöSž¿/Ž>d(ßò~&&A¢÷7ŒaßIÅ
aò,8Ñù3W|Îä„[ž£)Èa¡Á<ÂÖ
=ŒTÊ2ˆt)Œàp6F¬;.xÇq‘¯ìph§½Çœ®ÄÇC˜¯£6Ö+(E&fy7t•Ã%ú¸P‡‰6ÿ­X;èã!ŽO7çE¶MwNÌÃ6­r4Ü&œÙ¨És¯§CžØ,&&iËçÀ¿‡}s@l=ÖëžÔî›™âÆ¡ì$/Gì‚“Ñ=1¨NTδ¨Õfµ"†F™¦´Û°ßÐÛ•Îi!û¹Dñ1ª,:gñb³±â¦·¼zîæÑ¤@2Š
UÎSZ™ÈçG©Ÿˆ|Ø0@Ìó©ÿmŸ<0(ŒâÁ•ÈIJrÊ&u¿6ä.-V^yñ x枢‡Ã¯QA³"ByÅ<&hÑ–˜çÄ
ã¨KbuþôÁÿ ŒÃï
endstream

(注:“流”字前还有一些头信息,告诉你二进制数据有多长等)

我一直在做的是使用StreamReader 来读取文本数据,然后我想切换并只读取二进制数据。像这样的:

using (FileStream fs = new FileStream(myFile, FileMode.Open))
{
   fs.Seek(250205, SeekOrigin.Begin);  // This jumps to the start of the data above
   using (StreamReader sr = new StreamReader(fs))
   {
      String line = "";
      while ((line = sr.ReadLine()) != "stream");   // This skips to the end of "stream"

      // I want this to read the 2821 bytes AFTER stream
      byte[] buffer = new byte[2821];
      fs.Read(buffer, 0, buffer.Length);
   }
}

当我运行它时,buffer 不包含“流”之后的 2821 个字节。相反,它包含原始 Seek() 位置之后 1024 个字节的数据。

换句话说:我Seeked到250205的位置。然后,我读了几行(总共57个字节)。但我的buffer 从位置 251229(而不是 250262)开始。

如何让FileStreamStreamReader 停止的地方开始阅读?

(我这样做的主要原因是FileStream没有ReadLine()方法,而StreamReader没有byte[] = Read()方法。)

【问题讨论】:

  • 请帮自己一个忙,不要尝试在 PDF 文件中使用StreamReader。即使 pdf 内容部分看起来像文本格式,也不是。因此,您只会以这种方式在自己的脚下开枪。研究 pdf 规范、现有的 PDF 文档,也许还有其他 pdf 处理库。

标签: c# pdf io filestream


【解决方案1】:

对于性能问题,当您调用 Read/ReadLine 方法时,StreamReader 不会将您需要的确切字节数读入 Stream

它首先读取固定数量的字节,将它们存储到内部缓冲区中,然后从该缓冲区中获取您需要的字节。

当存储到内部缓冲区的所有数据都被读取后,会从相同的固定数量生成一个新的Read,依此类推......

当然,这个固定数量与内部缓冲区大小相匹配,可以根据msdn StreamReader constructor description

此构造函数将编码初始化为 UTF8Encoding,即 BaseStream 属性使用流参数,以及内部 缓冲区大小为 1024 字节。

因此,即使您的ReadLine 调用返回读取的总和为 57 个字节,您的StreamReader 至少已从您的FileStream 读取了 1024 个字节...

除其他外,一种解决方案可能是计算 ReadLines 调用返回的实际读取字节数(通过将 line.Length 相加到循环中)。然后从 Stream 的开头使用 Seekfs.Seek(250205 + sum, SeekOrigin.Begin); 再次使用这个 sum 变量。

话虽如此,我完全同意您在问题 cmets 中所说的话。使用StreamReader(专为阅读文本而设计)阅读PDF文件,也​​许你会得到一些惊喜。例如,您的 line 长度属性内容是否总是符合预期,可能是因为编码问题?

【讨论】:

    【解决方案2】:

    如果您需要从 StreamReader 获取和设置实际位置,请参阅https://stackoverflow.com/a/22975649/718033

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 1970-01-01
      • 2010-12-20
      • 2021-06-18
      • 1970-01-01
      • 2019-06-17
      • 2012-08-13
      相关资源
      最近更新 更多