Asp.net源码专业站
预留广告位
首页->博客空间->X3BLOG 单用户1.0 build80707(ACCESS)源代码>>SharpZipLib/Tar/TarInputStream.cs>>源码在线查看
温馨提示:代码在线浏览功能只能做为源码浏览参考,如果想更进一步了解该代码请下载:X3BLOG 单用户1.0 build80707(ACCESS)源代码
当前文件:文件类型 x3blogAccessBuild80707/SharpZipLib/Tar/TarInputStream.cs[18K,2009-6-12 11:58:58]打开代码结构图
普通视图
		            
1// TarInputStream.cs 2// 3// Copyright (C) 2001 Mike Krueger 4// 5// This program is free software; you can redistribute it and/or 6// modify it under the terms of the GNU General Public License 7// as published by the Free Software Foundation; either version 2 8// of the License, or (at your option) any later version. 9// 10// This program is distributed in the hope that it will be useful, 11// but WITHOUT ANY WARRANTY; without even the implied warranty of 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13// GNU General Public License for more details. 14// 15// You should have received a copy of the GNU General Public License 16// along with this program; if not, write to the Free Software 17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18// 19// Linking this library statically or dynamically with other modules is 20// making a combined work based on this library. Thus, the terms and 21// conditions of the GNU General Public License cover the whole 22// combination. 23// 24// As a special exception, the copyright holders of this library give you 25// permission to link this library with independent modules to produce an 26// executable, regardless of the license terms of these independent 27// modules, and to copy and distribute the resulting executable under 28// terms of your choice, provided that you also meet, for each linked 29// independent module, the terms and conditions of the license of that 30// module. An independent module is a module which is not derived from 31// or based on this library. If you modify this library, you may extend 32// this exception to your version of the library, but you are not 33// obligated to do so. If you do not wish to do so, delete this 34// exception statement from your version. 35 36using System; 37using System.IO; 38using System.Text; 39 40namespace ICSharpCode.SharpZipLib.Tar 41{ 42 43 /// <summary> 44 /// The TarInputStream reads a UNIX tar archive as an InputStream. 45 /// methods are provided to position at each successive entry in 46 /// the archive, and the read each entry as a normal input stream 47 /// using read(). 48 /// </summary> 49 public class TarInputStream : Stream 50 { 51 /// <summary> 52 /// Flag set when last block has been read 53 /// </summary> 54 protected bool hasHitEOF; 55 56 /// <summary> 57 /// Size of this entry as recorded in header 58 /// </summary> 59 protected long entrySize; 60 61 /// <summary> 62 /// Number of bytes read for this entry so far 63 /// </summary> 64 protected long entryOffset; 65 66 /// <summary> 67 /// Buffer used with calls to <code>Read()</code> 68 /// </summary> 69 protected byte[] readBuf; 70 71 /// <summary> 72 /// Working buffer 73 /// </summary> 74 protected TarBuffer buffer; 75 76 /// <summary> 77 /// Current entry being read 78 /// </summary> 79 protected TarEntry currEntry; 80 81 /// <summary> 82 /// Factory used to create TarEntry or descendant class instance 83 /// </summary> 84 protected IEntryFactory eFactory; 85 86 Stream inputStream; 87 88 /// <summary> 89 /// Gets a value indicating whether the current stream supports reading 90 /// </summary> 91 public override bool CanRead { 92 get { 93 return inputStream.CanRead; 94 } 95 } 96 97 /// <summary> 98 /// Gets a value indicating whether the current stream supports seeking 99 /// This property always returns false. 100 /// </summary> 101 public override bool CanSeek { 102 get { 103 return false; 104 } 105 } 106 107 /// <summary> 108 /// Gets a value indicating if the stream supports writing. 109 /// This property always returns false. 110 /// </summary> 111 public override bool CanWrite { 112 get { 113 return false; 114 } 115 } 116 117 /// <summary> 118 /// The length in bytes of the stream 119 /// </summary> 120 public override long Length { 121 get { 122 return inputStream.Length; 123 } 124 } 125 126 /// <summary> 127 /// Gets or sets the position within the stream. 128 /// Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException 129 /// </summary> 130 /// <exception cref="NotSupportedException">Any attempt to set position</exception> 131 public override long Position { 132 get { 133 return inputStream.Position; 134 } 135 set { 136 throw new NotSupportedException("TarInputStream Seek not supported"); 137 } 138 } 139 140 /// <summary> 141 /// Flushes the baseInputStream 142 /// </summary> 143 public override void Flush() 144 { 145 inputStream.Flush(); 146 } 147 148 /// <summary> 149 /// Set the streams position. This operation is not supported and will throw a NotSupportedException 150 /// </summary> 151 /// <exception cref="NotSupportedException">Any access</exception> 152 public override long Seek(long offset, SeekOrigin origin) 153 { 154 throw new NotSupportedException("TarInputStream Seek not supported"); 155 } 156 157 /// <summary> 158 /// Sets the length of the stream 159 /// This operation is not supported and will throw a NotSupportedException 160 /// </summary> 161 /// <exception cref="NotSupportedException">Any access</exception> 162 public override void SetLength(long val) 163 { 164 throw new NotSupportedException("TarInputStream SetLength not supported"); 165 } 166 167 /// <summary> 168 /// Writes a block of bytes to this stream using data from a buffer. 169 /// This operation is not supported and will throw a NotSupportedException 170 /// </summary> 171 /// <exception cref="NotSupportedException">Any access</exception> 172 public override void Write(byte[] array, int offset, int count) 173 { 174 throw new NotSupportedException("TarInputStream Write not supported"); 175 } 176 177 /// <summary> 178 /// Writes a byte to the current position in the file stream. 179 /// This operation is not supported and will throw a NotSupportedException 180 /// </summary> 181 /// <exception cref="NotSupportedException">Any access</exception> 182 public override void WriteByte(byte val) 183 { 184 throw new NotSupportedException("TarInputStream WriteByte not supported"); 185 } 186 187 188 /// <summary> 189 /// Construct a TarInputStream with default block factor 190 /// </summary> 191 /// <param name="inputStream">stream to source data from</param> 192 public TarInputStream(Stream inputStream) : this(inputStream, TarBuffer.DefaultBlockFactor) 193 { 194 } 195 196 /// <summary> 197 /// Construct a TarInputStream with user specified block factor 198 /// </summary> 199 /// <param name="inputStream">stream to source data from</param> 200 /// <param name="blockFactor">block factor to apply to archive</param> 201 public TarInputStream(Stream inputStream, int blockFactor) 202 { 203 this.inputStream = inputStream; 204 this.buffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor); 205 206 this.readBuf = null; 207 this.hasHitEOF = false; 208 this.eFactory = null; 209 } 210 211 /// <summary> 212 /// Set the entry factory for this instance. 213 /// </summary> 214 /// <param name="factory">The factory for creating new entries</param> 215 public void SetEntryFactory(IEntryFactory factory) 216 { 217 this.eFactory = factory; 218 } 219 220 /// <summary> 221 /// Closes this stream. Calls the TarBuffer's close() method. 222 /// The underlying stream is closed by the TarBuffer. 223 /// </summary> 224 public override void Close() 225 { 226 this.buffer.Close(); 227 } 228 229 /// <summary> 230 /// Get the record size being used by this stream's TarBuffer. 231 /// </summary> 232 /// <returns> 233 /// TarBuffer record size. 234 /// </returns> 235 public int GetRecordSize() 236 { 237 return this.buffer.GetRecordSize(); 238 } 239 240 /// <summary> 241 /// Get the available data that can be read from the current 242 /// entry in the archive. This does not indicate how much data 243 /// is left in the entire archive, only in the current entry. 244 /// This value is determined from the entry's size header field 245 /// and the amount of data already read from the current entry. 246 /// </summary> 247 /// <returns> 248 /// The number of available bytes for the current entry. 249 /// </returns> 250 public long Available { 251 get { 252 return this.entrySize - this.entryOffset; 253 } 254 } 255 256 /// <summary> 257 /// Skip bytes in the input buffer. This skips bytes in the 258 /// current entry's data, not the entire archive, and will 259 /// stop at the end of the current entry's data if the number 260 /// to skip extends beyond that point. 261 /// </summary> 262 /// <param name="numToSkip"> 263 /// The number of bytes to skip. 264 /// </param> 265 public void Skip(long numToSkip) 266 { 267 // TODO: REVIEW 268 // This is horribly inefficient, but it ensures that we 269 // properly skip over bytes via the TarBuffer... 270 // 271 byte[] skipBuf = new byte[8 * 1024]; 272 273 for (long num = numToSkip; num > 0;) { 274 int toRead = num > skipBuf.Length ? skipBuf.Length : (int)num; 275 int numRead = this.Read(skipBuf, 0, toRead); 276 277 if (numRead == -1) { 278 break; 279 } 280 281 num -= numRead; 282 } 283 } 284 285 /// <summary> 286 /// Since we do not support marking just yet, we return false. 287 /// </summary> 288 public bool IsMarkSupported { 289 get { 290 return false; 291 } 292 } 293 294 /// <summary> 295 /// Since we do not support marking just yet, we do nothing. 296 /// </summary> 297 /// <param name ="markLimit"> 298 /// The limit to mark. 299 /// </param> 300 public void Mark(int markLimit) 301 { 302 } 303 304 /// <summary> 305 /// Since we do not support marking just yet, we do nothing. 306 /// </summary> 307 public void Reset() 308 { 309 } 310 311 void SkipToNextEntry() 312 { 313 long numToSkip = this.entrySize - this.entryOffset; 314 315 if (numToSkip > 0) { 316 this.Skip(numToSkip); 317 } 318 319 this.readBuf = null; 320 } 321 322 /// <summary> 323 /// Get the next entry in this tar archive. This will skip 324 /// over any remaining data in the current entry, if there 325 /// is one, and place the input stream at the header of the 326 /// next entry, and read the header and instantiate a new 327 /// TarEntry from the header bytes and return that entry. 328 /// If there are no more entries in the archive, null will 329 /// be returned to indicate that the end of the archive has 330 /// been reached. 331 /// </summary> 332 /// <returns> 333 /// The next TarEntry in the archive, or null. 334 /// </returns> 335 public TarEntry GetNextEntry() 336 { 337 if (this.hasHitEOF) { 338 return null; 339 } 340 341 if (this.currEntry != null) { 342 SkipToNextEntry(); 343 } 344 345 byte[] headerBuf = this.buffer.ReadBlock(); 346 347 if (headerBuf == null) { 348 this.hasHitEOF = true; 349 } else if (this.buffer.IsEOFBlock(headerBuf)) { 350 this.hasHitEOF = true; 351 } 352 353 if (this.hasHitEOF) { 354 this.currEntry = null; 355 } else { 356 try { 357 TarHeader header = new TarHeader(); 358 header.ParseBuffer(headerBuf); 359 if ( !header.IsChecksumValid ) 360 { 361 throw new TarException("Header checksum is invalid"); 362 } 363 this.entryOffset = 0; 364 this.entrySize = header.Size; 365 366 StringBuilder longName = null; 367 368 if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) { 369 370 byte[] nameBuffer = new byte[TarBuffer.BlockSize]; 371 372 long numToRead = this.entrySize; 373 374 longName = new StringBuilder(); 375 376 while (numToRead > 0) { 377 int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead)); 378 379 if (numRead == -1) { 380 throw new InvalidHeaderException("Failed to read long name entry"); 381 } 382 383 longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString()); 384 numToRead -= numRead; 385 } 386 387 SkipToNextEntry(); 388 headerBuf = this.buffer.ReadBlock(); 389 } else if (header.TypeFlag == TarHeader.LF_GHDR) { // POSIX global extended header 390 // Ignore things we dont understand completely for now 391 SkipToNextEntry(); 392 headerBuf = this.buffer.ReadBlock(); 393 } else if (header.TypeFlag == TarHeader.LF_XHDR) { // POSIX extended header 394 // Ignore things we dont understand completely for now 395 SkipToNextEntry(); 396 headerBuf = this.buffer.ReadBlock(); 397 } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) { 398 // TODO: could show volume name when verbose 399 SkipToNextEntry(); 400 headerBuf = this.buffer.ReadBlock(); 401 } else if (header.TypeFlag != TarHeader.LF_NORMAL && 402 header.TypeFlag != TarHeader.LF_OLDNORM && 403 header.TypeFlag != TarHeader.LF_DIR) { 404 // Ignore things we dont understand completely for now 405 SkipToNextEntry(); 406 headerBuf = this.buffer.ReadBlock(); 407 } 408 409 if (this.eFactory == null) { 410 this.currEntry = new TarEntry(headerBuf); 411 if (longName != null) { 412 currEntry.Name = longName.ToString(); 413 } 414 } else { 415 this.currEntry = this.eFactory.CreateEntry(headerBuf); 416 } 417 418 // Magic was checked here for 'ustar' but there are multiple valid possibilities 419 // so this is not done anymore. 420 421 this.entryOffset = 0; 422 423 // TODO: Review How do we resolve this discrepancy?! 424 this.entrySize = this.currEntry.Size; 425 } catch (InvalidHeaderException ex) { 426 this.entrySize = 0; 427 this.entryOffset = 0; 428 this.currEntry = null; 429 throw new InvalidHeaderException("bad header in record " + this.buffer.GetCurrentBlockNum() + " block " + this.buffer.GetCurrentBlockNum() + ", " + ex.Message); 430 } 431 } 432 return this.currEntry; 433 } 434 435 /// <summary> 436 /// Reads a byte from the current tar archive entry. 437 /// This method simply calls read(byte[], int, int). 438 /// </summary> 439 public override int ReadByte() 440 { 441 byte[] oneByteBuffer = new byte[1]; 442 int num = this.Read(oneByteBuffer, 0, 1); 443 if (num <= 0) { // return -1 to indicate that no byte was read. 444 return -1; 445 } 446 return (int)oneByteBuffer[0]; 447 } 448 449 /// <summary> 450 /// Reads bytes from the current tar archive entry. 451 /// 452 /// This method is aware of the boundaries of the current 453 /// entry in the archive and will deal with them appropriately 454 /// </summary> 455 /// <param name="outputBuffer"> 456 /// The buffer into which to place bytes read. 457 /// </param> 458 /// <param name="offset"> 459 /// The offset at which to place bytes read. 460 /// </param> 461 /// <param name="count"> 462 /// The number of bytes to read. 463 /// </param> 464 /// <returns> 465 /// The number of bytes read, or 0 at end of stream/EOF. 466 /// </returns> 467 public override int Read(byte[] outputBuffer, int offset, int count) 468 { 469 int totalRead = 0; 470 471 if (this.entryOffset >= this.entrySize) { 472 return 0; 473 } 474 475 long numToRead = count; 476 477 if ((numToRead + this.entryOffset) > this.entrySize) { 478 numToRead = this.entrySize - this.entryOffset; 479 } 480 481 if (this.readBuf != null) { 482 int sz = (numToRead > this.readBuf.Length) ? this.readBuf.Length : (int)numToRead; 483 484 Array.Copy(this.readBuf, 0, outputBuffer, offset, sz); 485 486 if (sz >= this.readBuf.Length) { 487 this.readBuf = null; 488 } else { 489 int newLen = this.readBuf.Length - sz; 490 byte[] newBuf = new byte[newLen]; 491 Array.Copy(this.readBuf, sz, newBuf, 0, newLen); 492 this.readBuf = newBuf; 493 } 494 495 totalRead += sz; 496 numToRead -= sz; 497 offset += sz; 498 } 499 500 while (numToRead > 0) { 501 byte[] rec = this.buffer.ReadBlock(); 502 if (rec == null) { 503 // Unexpected EOF! 504 throw new TarException("unexpected EOF with " + numToRead + " bytes unread"); 505 } 506 507 int sz = (int)numToRead; 508 int recLen = rec.Length; 509 510 if (recLen > sz) { 511 Array.Copy(rec, 0, outputBuffer, offset, sz); 512 this.readBuf = new byte[recLen - sz]; 513 Array.Copy(rec, sz, this.readBuf, 0, recLen - sz); 514 } else { 515 sz = recLen; 516 Array.Copy(rec, 0, outputBuffer, offset, recLen); 517 } 518 519 totalRead += sz; 520 numToRead -= sz; 521 offset += sz; 522 } 523 524 this.entryOffset += totalRead; 525 526 return totalRead; 527 } 528 529 /// <summary> 530 /// Copies the contents of the current tar archive entry directly into 531 /// an output stream. 532 /// </summary> 533 /// <param name="outputStream"> 534 /// The OutputStream into which to write the entry's data. 535 /// </param> 536 public void CopyEntryContents(Stream outputStream) 537 { 538 byte[] buf = new byte[32 * 1024]; 539 540 while (true) { 541 int numRead = this.Read(buf, 0, buf.Length); 542 if (numRead <= 0) { 543 break; 544 } 545 outputStream.Write(buf, 0, numRead); 546 } 547 } 548 549 /// <summary> 550 /// This interface is provided, along with the method setEntryFactory(), to allow 551 /// the programmer to have their own TarEntry subclass instantiated for the 552 /// entries return from getNextEntry(). 553 /// </summary> 554 public interface IEntryFactory 555 { 556 /// <summary> 557 /// Create an entry based on name alone 558 /// </summary> 559 /// <param name="name"> 560 /// Name of the new EntryPointNotFoundException to create 561 /// </param> 562 /// <returns>created TarEntry or descendant class</returns> 563 TarEntry CreateEntry(string name); 564 565 /// <summary> 566 /// Create an instance based on an actual file 567 /// </summary> 568 /// <param name="fileName"> 569 /// Name of file to represent in the entry 570 /// </param> 571 /// <returns> 572 /// Created TarEntry or descendant class 573 /// </returns> 574 TarEntry CreateEntryFromFile(string fileName); 575 576 /// <summary> 577 /// Create a tar entry based on the header information passed 578 /// </summary> 579 /// <param name="headerBuf"> 580 /// Buffer containing header information to base entry on 581 /// </param> 582 /// <returns> 583 /// Created TarEntry or descendant class 584 /// </returns> 585 TarEntry CreateEntry(byte[] headerBuf); 586 } 587 588 /// <summary> 589 /// Standard entry factory class creating instances of the class TarEntry 590 /// </summary> 591 public class EntryFactoryAdapter : IEntryFactory 592 { 593 /// <summary> 594 /// Create a TarEntry based on named 595 /// </summary> 596 public TarEntry CreateEntry(string name) 597 { 598 return TarEntry.CreateTarEntry(name); 599 } 600 601 /// <summary> 602 /// Create a tar entry with details obtained from <paramref name="fileName">file</paramref> 603 /// </summary> 604 public TarEntry CreateEntryFromFile(string fileName) 605 { 606 return TarEntry.CreateEntryFromFile(fileName); 607 } 608 609 /// <summary> 610 /// Create and entry based on details in <paramref name="headerBuf">header</paramref> 611 /// </summary> 612 public TarEntry CreateEntry(byte[] headerBuf) 613 { 614 return new TarEntry(headerBuf); 615 } 616 } 617 } 618 619 620} 621 622/* The original Java file had this header: 623 ** Authored by Timothy Gerard Endres 624 ** <mailto:time@gjt.org> <http://www.trustice.com> 625 ** 626 ** This work has been placed into the public domain. 627 ** You may use this work in any way and for any purpose you wish. 628 ** 629 ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, 630 ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR 631 ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY 632 ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR 633 ** REDISTRIBUTION OF THIS SOFTWARE. 634 ** 635 */ 636 637
还没有找到您心仪的内容?请用.net源码大搜捕
代码片断 打包下载该项目完整源码:X3BLOG 单用户1.0 build80707(ACCESS)源代码
51Aspx.com 版权所有 CopyRight © 2006-2010. 京ICP备06046876号 本站法律顾问:ITlaw-庄毅雄律师
返回顶部
客户服务:点击这里进行客户咨询 业务合作:点击这里洽谈业务合作 合作热线:010-68880146