チェンジセット 1692 (default)
- 日時:
- 2024/10/02 22:41:28 (4日前)
- 場所:
- framework/trunk
- ファイル:
-
- 2個の更新
凡例:
- 未変更
- 追加
- 削除
-
framework/trunk/CoreLibrary/Sources/IO/IOUtility.cs
r1690 r1692 1137 1137 /// I/O エラーが発生しました。 1138 1138 /// </exception> 1139 [Obsolete("Use ReadToEnd()", false)] 1139 1140 public static byte[] ReadAll(Stream stream) 1140 1141 { 1141 // 引数をチェック 1142 if (stream == null) 1143 { 1144 throw new ArgumentNullException("stream"); 1145 } 1146 1147 const int BufferSize = 0x2000; 1148 1149 using (MemoryStream memoryStream = new MemoryStream()) 1150 { 1151 int readLength; 1152 byte[] buffer = new byte[BufferSize]; 1153 while ((readLength = stream.Read(buffer, 0, BufferSize)) > 0) 1154 { 1155 memoryStream.Write(buffer, 0, readLength); 1156 } 1157 1158 return memoryStream.ToArray(); 1159 } 1142 return ReadToEnd(stream); 1160 1143 } 1161 1144 … … 1376 1359 length)); 1377 1360 } 1361 } 1362 1363 /// <summary> 1364 /// ストリームからバイトシーケンスを読み取り、読み取ったバイト数の分だけストリームの位置を進めます。 1365 /// </summary> 1366 /// <param name="stream">読み取るストリーム。</param> 1367 /// <param name="buffer"> 1368 /// バイト配列。このメソッドが戻るとき、指定したバイト配列の <paramref name="offset"/> 1369 /// から (<paramref name="offset"/> + <paramref name="count"/> -1) までの値が、 1370 /// 現在のソースから読み取られたバイトに置き換えられます。 1371 /// </param> 1372 /// <param name="offset"> 1373 /// 読み取ったデータの格納を開始する位置を示す 1374 /// <paramref name="buffer"/> 内のバイト オフセット。インデックス番号は <c>0</c> から始まります。 1375 /// </param> 1376 /// <param name="count">現在のストリームから読み取るバイト数。</param> 1377 /// <returns> 1378 /// ストリームから読み取り <paramref name="buffer"/> に格納したバイト数。 1379 /// </returns> 1380 /// <exception cref="ArgumentNullException"> 1381 /// <paramref name="stream"/> または 1382 /// <paramref name="buffer"/> が <see langword="null"/> です。 1383 /// </exception> 1384 /// <exception cref="ArgumentOutOfRangeException"> 1385 /// <paramref name="offset"/> または 1386 /// <paramref name="count"/> が負の値です。 1387 /// </exception> 1388 /// <exception cref="ArgumentException"> 1389 /// <paramref name="offset"/> と <paramref name="count"/> が 1390 /// <paramref name="buffer"/> の無効な範囲を示しています。 1391 /// </exception> 1392 /// <exception cref="IOException"> 1393 /// I/O エラーが発生しました。 1394 /// </exception> 1395 public static int Fill(Stream stream, byte[] buffer, int offset, int count) 1396 { 1397 // ReSharper disable once ExceptionNotDocumented 1398 return Fill(stream, buffer, offset, count, false); 1399 } 1400 1401 /// <summary> 1402 /// ストリームからバイトシーケンスを読み取り、読み取ったバイト数の分だけストリームの位置を進めます。 1403 /// </summary> 1404 /// <param name="stream">読み取るストリーム。</param> 1405 /// <param name="buffer"> 1406 /// バイト配列。このメソッドが戻るとき、指定したバイト配列の <paramref name="offset"/> 1407 /// から (<paramref name="offset"/> + <paramref name="count"/> -1) までの値が、 1408 /// 現在のソースから読み取られたバイトに置き換えられます。 1409 /// </param> 1410 /// <param name="offset"> 1411 /// 読み取ったデータの格納を開始する位置を示す 1412 /// <paramref name="buffer"/> 内のバイト オフセット。インデックス番号は <c>0</c> から始まります。 1413 /// </param> 1414 /// <param name="count">現在のストリームから読み取るバイト数。</param> 1415 /// <param name="throwOnNotEnough"> 1416 /// <paramref name="count"/> で指定したバイト数分だけ読み込む前にストリームの末尾に達した時に例外を投げる場合は <see langword="true"/>。 1417 /// それ以外の場合は <see langword="false"/>。 1418 /// </param> 1419 /// <returns> 1420 /// ストリームから読み取り <paramref name="buffer"/> に格納したバイト数。 1421 /// </returns> 1422 /// <exception cref="ArgumentNullException"> 1423 /// <paramref name="stream"/> または 1424 /// <paramref name="buffer"/> が <see langword="null"/> です。 1425 /// </exception> 1426 /// <exception cref="ArgumentOutOfRangeException"> 1427 /// <paramref name="offset"/> または 1428 /// <paramref name="count"/> が負の値です。 1429 /// </exception> 1430 /// <exception cref="ArgumentException"> 1431 /// <paramref name="offset"/> と <paramref name="count"/> が 1432 /// <paramref name="buffer"/> の無効な範囲を示しています。 1433 /// </exception> 1434 /// <exception cref="IOException"> 1435 /// I/O エラーが発生しました。 1436 /// </exception> 1437 /// <exception cref="EndOfStreamException"> 1438 /// <paramref name="throwOnNotEnough"/> に <see langword="true"/> が指定されていて 1439 /// <paramref name="count"/> を読み込む前にストリームの末尾に達しました。 1440 /// </exception> 1441 public static int Fill(Stream stream, byte[] buffer, int offset, int count, bool throwOnNotEnough) 1442 { 1443 // 引数をチェック 1444 if (stream == null) 1445 { 1446 throw new ArgumentNullException("stream"); 1447 } 1448 1449 1450 if (buffer == null) 1451 { 1452 throw new ArgumentNullException("buffer"); 1453 } 1454 1455 if (offset < 0) 1456 { 1457 throw new ArgumentOutOfRangeException( 1458 "offset", 1459 offset, 1460 Resources.ArgumentOutOfRange_NeedNonNegNum); 1461 } 1462 1463 if (count < 0) 1464 { 1465 throw new ArgumentOutOfRangeException( 1466 "count", 1467 count, 1468 Resources.ArgumentOutOfRange_NeedNonNegNum); 1469 } 1470 1471 if (buffer.Length - offset < count) 1472 { 1473 throw new ArgumentException( 1474 Resources.Argument_InvalidOffLen); 1475 } 1476 1477 if (count == 0) 1478 { 1479 return 0; 1480 } 1481 1482 int remainingCount = count; 1483 for (;;) 1484 { 1485 int readLength; 1486 if ((readLength = stream.Read(buffer, offset, remainingCount)) == 0) 1487 { 1488 if (throwOnNotEnough) 1489 { 1490 throw new EndOfStreamException(); 1491 } 1492 1493 return count - remainingCount; 1494 } 1495 1496 // 全て読み込んだ場合 1497 if (readLength == remainingCount) 1498 { 1499 return count; 1500 } 1501 1502 offset += readLength; 1503 remainingCount -= readLength; 1504 } 1505 } 1506 1507 /// <summary> 1508 /// ストリームの末尾まで読み取りバイト配列で返します。 1509 /// </summary> 1510 /// <param name="stream">読み込むストリーム。</param> 1511 /// <returns> 1512 /// 末尾まででのデータを格納したバイト配列。 1513 /// </returns> 1514 /// <exception cref="ArgumentNullException"> 1515 /// <paramref name="stream"/> が <see langword="null"/> です。 1516 /// </exception> 1517 /// <exception cref="IOException"> 1518 /// I/O エラーが発生しました。 1519 /// </exception> 1520 public static byte[] ReadToEnd(Stream stream) 1521 { 1522 return ReadToEnd(stream, int.MaxValue, 0x1000); 1523 } 1524 1525 /// <summary> 1526 /// ストリームの末尾まで読み取りバイト配列で返します。 1527 /// </summary> 1528 /// <param name="stream">読み込むストリーム。</param> 1529 /// <param name="limitSize">読み取り可能な最大のバイト数。</param> 1530 /// <param name="blockSize">読み込む時に使用するブロックサイズ。</param> 1531 /// <returns> 1532 /// 末尾まででのデータを格納したバイト配列。 1533 /// </returns> 1534 /// <exception cref="ArgumentNullException"> 1535 /// <paramref name="stream"/> が <see langword="null"/> です。 1536 /// </exception> 1537 /// <exception cref="ArgumentOutOfRangeException"> 1538 /// <paramref name="limitSize"/> が 0 未満、または 1539 /// <paramref name="blockSize"/> が 1 未満です。 1540 /// </exception> 1541 /// <exception cref="IOException"> 1542 /// I/O エラーが発生しました。 1543 /// </exception> 1544 public static byte[] ReadToEnd(Stream stream, int limitSize, int blockSize) 1545 { 1546 // 引数をチェック 1547 if (stream == null) 1548 { 1549 throw new ArgumentNullException("stream"); 1550 } 1551 1552 if (limitSize < 0) 1553 { 1554 throw new ArgumentOutOfRangeException( 1555 "limitSize", 1556 limitSize, 1557 Resources.ArgumentOutOfRange_NeedNonNegNum); 1558 } 1559 1560 if (blockSize <= 0) 1561 { 1562 throw new ArgumentOutOfRangeException( 1563 "blockSize", 1564 blockSize, 1565 string.Format( 1566 CultureInfo.CurrentCulture, 1567 Resources.ArgumentOutOfRange_MustBeOneOrGreater, 1568 "blockSize")); 1569 } 1570 1571 // リミットが 0 の場合は読み込まずに返す 1572 if (limitSize == 0) 1573 { 1574 return new byte[0]; 1575 } 1576 1577 // ブロックサイズよりリミットの方が小さい場合は、ブロックサイズをリミットに合わせる 1578 if (limitSize < blockSize) 1579 { 1580 blockSize = limitSize; 1581 } 1582 1583 int bufferLength = blockSize; 1584 byte[] buffer = new byte[bufferLength]; 1585 int offset = 0; 1586 int readLength; 1587 while ((readLength = stream.Read(buffer, offset, blockSize)) != 0) 1588 { 1589 offset += readLength; 1590 1591 // リミットまで読み込んだ場合 1592 if (offset == limitSize) 1593 { 1594 Debug.Assert(bufferLength == limitSize, "Invalid buffer size"); 1595 return buffer; 1596 } 1597 1598 // 残りの部分に読み込める場合 1599 if (bufferLength - offset >= blockSize) 1600 { 1601 continue; 1602 } 1603 1604 int newBufferLength; 1605 if (limitSize - bufferLength >= bufferLength) 1606 { 1607 // 2 倍に拡張 1608 newBufferLength = bufferLength * 2; 1609 } 1610 else if (bufferLength < limitSize) 1611 { 1612 // 2 倍までは拡張できない場合は、全体で limitSize になるようにする 1613 newBufferLength = limitSize; 1614 1615 // 読み込み可能な残りのサイズがブロックサイズより小さい場合は、ブロックサイズを残りのサイズに合わせる 1616 if (newBufferLength - offset < blockSize) 1617 { 1618 blockSize = newBufferLength - offset; 1619 } 1620 } 1621 else 1622 { 1623 // これ以上拡張できない場合 1624 1625 // 読み込み可能な残りのサイズがブロックサイズより小さい場合は、ブロックサイズを残りのサイズに合わせる 1626 if (bufferLength - offset < blockSize) 1627 { 1628 blockSize = bufferLength - offset; 1629 } 1630 1631 continue; 1632 } 1633 1634 // バッファを拡張 1635 byte[] newBuffer = new byte[newBufferLength]; 1636 Buffer.BlockCopy(buffer, 0, newBuffer, 0, offset); 1637 buffer = newBuffer; 1638 bufferLength = newBufferLength; 1639 } 1640 1641 // ストリームの末尾に達した場合は、バッファの末尾には必ず余りがあるので削除 1642 byte[] resultBuffer = new byte[offset]; 1643 Buffer.BlockCopy(buffer, 0, resultBuffer, 0, offset); 1644 return resultBuffer; 1378 1645 } 1379 1646 -
framework/trunk/CoreTest/Sources/IO/IOUtilityTest.cs
r1690 r1692 29 29 using System.Globalization; 30 30 using System.IO; 31 using System.Linq; 31 32 using System.Text; 32 33 using FCSoft.SilverFrost.Framework.Security; 34 using FCSoft.SilverFrost.Framework.Test; 33 35 using FCSoft.SilverFrost.Framework.Text; 34 36 using FCSoft.SilverFrost.Framework.UnitTest; … … 772 774 773 775 /// <summary> 776 /// <see cref="IOUtility.Fill(System.IO.Stream,byte[],int,int)"/> をテストします。 777 /// </summary> 778 /// <param name="bufferSize">読み込む時に使用するバッファサイズ。</param> 779 /// <param name="maxReadSize">一度に読める最大サイズ。</param> 780 [Test] 781 [TestCase(0, 4)] 782 [TestCase(1, 4)] 783 [TestCase(2, 4)] 784 [TestCase(3, 4)] 785 [TestCase(4, 4)] 786 [TestCase(5, 4)] 787 [TestCase(6, 4)] 788 [TestCase(7, 4)] 789 [TestCase(8, 4)] 790 [TestCase(9, 4)] 791 [TestCase(16, 4)] 792 [TestCase(16, 16)] 793 [TestCase(20, 4)] 794 [TestCase(20, 16)] 795 public void TestFill(int bufferSize, int maxReadSize) 796 { 797 byte[] sourceData = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x8, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; 798 799 using (MemoryStream memoryStream = new MemoryStream(sourceData, false)) 800 { 801 using (ReadSizeLimitedStream readSizeLimitedStream = new ReadSizeLimitedStream(memoryStream, maxReadSize)) 802 { 803 byte[] buffer = new byte[bufferSize + 2]; 804 for (int i = 0; i < buffer.Length; i++) 805 { 806 buffer[i] = 0xFF; 807 } 808 809 Assert.That( 810 IOUtility.Fill(readSizeLimitedStream, buffer, 1, bufferSize), 811 Is.EqualTo(Math.Min(bufferSize, sourceData.Length)), 812 "Fill"); 813 814 byte[] expectedData = new byte[bufferSize + 2]; 815 for (int i = 0; i < buffer.Length; i++) 816 { 817 expectedData[i] = 0xFF; 818 } 819 820 Buffer.BlockCopy(sourceData, 0, expectedData, 1, Math.Min(bufferSize, sourceData.Length)); 821 822 Assert.That(buffer, Is.EqualTo(expectedData), "Buffer"); 823 } 824 } 825 } 826 827 /// <summary> 828 /// <see cref="IOUtility.ReadToEnd(System.IO.Stream,int,int)"/> をテストします。 829 /// </summary> 830 /// <param name="limitSize">読み取り可能な最大のバイト数。</param> 831 /// <param name="blockSize">読み込む時に使用するブロックサイズ。</param> 832 /// <param name="maxReadSize">一度に読める最大サイズ。</param> 833 [Test] 834 [TestCase(0, 1, 4)] 835 [TestCase(1, 2, 4)] 836 [TestCase(2, 2, 4)] 837 [TestCase(3, 2, 4)] 838 [TestCase(4, 2, 4)] 839 [TestCase(5, 2, 4)] 840 [TestCase(6, 2, 4)] 841 [TestCase(7, 2, 4)] 842 [TestCase(8, 2, 4)] 843 [TestCase(9, 2, 4)] 844 [TestCase(1, 2, 1)] 845 [TestCase(2, 2, 1)] 846 [TestCase(3, 2, 1)] 847 [TestCase(4, 2, 1)] 848 [TestCase(5, 2, 1)] 849 [TestCase(6, 2, 1)] 850 [TestCase(7, 2, 1)] 851 [TestCase(8, 2, 1)] 852 [TestCase(9, 2, 1)] 853 [TestCase(1, 3, 2)] 854 [TestCase(2, 3, 2)] 855 [TestCase(3, 3, 2)] 856 [TestCase(4, 3, 2)] 857 [TestCase(5, 3, 2)] 858 [TestCase(6, 3, 2)] 859 [TestCase(7, 3, 2)] 860 [TestCase(8, 3, 2)] 861 [TestCase(9, 3, 2)] 862 public void TestReadToEnd(int limitSize, int blockSize, int maxReadSize) 863 { 864 byte[] sourceData = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x8, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; 865 866 using (MemoryStream memoryStream = new MemoryStream(sourceData, false)) 867 { 868 using (ReadSizeLimitedStream readSizeLimitedStream = new ReadSizeLimitedStream(memoryStream, maxReadSize)) 869 { 870 byte[] resultData = IOUtility.ReadToEnd(readSizeLimitedStream, limitSize, blockSize); 871 872 Assert.That(resultData, Is.EqualTo(sourceData.Take(limitSize).ToArray())); 873 } 874 } 875 } 876 877 /// <summary> 774 878 /// <see cref="IOUtility.CreateCloseExceptionIgnorableTextWriter"/> をテストします。 775 879 /// </summary> … … 868 972 } 869 973 } 974 975 976 /// <summary> 977 /// 一度に読み込める最大のサイズの制限があるストリームです。 978 /// </summary> 979 private sealed class ReadSizeLimitedStream : 980 FilterStream 981 { 982 /// <summary> 983 /// 一度に読み込める最大のサイズ。 984 /// </summary> 985 private readonly int maxReadSize; 986 987 988 /// <summary> 989 /// インスタンスを作成します。 990 /// </summary> 991 /// <param name="stream">元にするストリーム。</param> 992 /// <param name="maxReadSize">一度に読み込める最大のサイズ。</param> 993 internal ReadSizeLimitedStream(Stream stream, int maxReadSize) 994 : base(stream, true) 995 { 996 this.maxReadSize = maxReadSize; 997 } 998 999 /// <summary> 1000 /// 現在のストリームからバイト シーケンスを読み取り、読み取ったバイト数の分だけストリームの位置を進めます。 1001 /// </summary> 1002 /// <param name="buffer"> 1003 /// バイト配列。このメソッドが戻るとき、指定したバイト配列の 1004 /// <paramref name="offset"/> から 1005 /// (<paramref name="offset"/> + <paramref name="count"/> <c>-1</c>) までの値が、 1006 /// 現在のソースから読み取られたバイトに置き換えられます。 1007 /// </param> 1008 /// <param name="offset"> 1009 /// 現在のストリームから読み取ったデータの格納を開始する位置を示す 1010 /// <paramref name="buffer"/> 内のバイト オフセット。 1011 /// インデックス番号は <c>0</c> から始まります。 1012 /// </param> 1013 /// <param name="count"> 1014 /// 現在のストリームから読み取る最大バイト数。 1015 /// </param> 1016 /// <returns> 1017 /// バッファに読み取られた合計バイト数。 1018 /// 要求しただけのバイト数を読み取ることができなかった場合、 1019 /// この値は要求したバイト数より小さくなります。 1020 /// ストリームの末尾に到達した場合は <c>0</c> (ゼロ) になることがあります。 1021 /// </returns> 1022 /// <exception cref="ArgumentException"> 1023 /// <paramref name="offset"/> と <paramref name="count"/> の合計値が、バッファ長より大きい値です。 1024 /// </exception> 1025 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> が <see langword="null"/> です。 1026 /// </exception> 1027 /// <exception cref="ArgumentOutOfRangeException"> 1028 /// <paramref name="offset"/> または <paramref name="count"/> が負の値です。 1029 /// </exception> 1030 /// <exception cref="IOException"> 1031 /// I/O エラーが発生しました。 1032 /// </exception> 1033 /// <exception cref="NotSupportedException"> 1034 /// ストリームが読み取りをサポートしていません。 1035 /// </exception> 1036 /// <exception cref="ObjectDisposedException"> 1037 /// ストリームが閉じられた後でメソッドが呼び出されました。 1038 /// </exception> 1039 public override int Read(byte[] buffer, int offset, int count) 1040 { 1041 return base.Read(buffer, offset, Math.Min(count, maxReadSize)); 1042 } 1043 } 870 1044 } 871 1045 }
※ 詳しい使い方は
TracChangeset を参照してください。