바이트 배열을 기본 null 이외의 특정 값으로 초기화 하시겠습니까? [복제]
이 질문에는 이미 답변이 있습니다.
- C #에서 memset에 해당하는 것은 무엇입니까? 답변 14 개
C ++에서 수행 한 오래된 프로젝트를 C #으로 다시 작성하는 데 바쁩니다.
내 임무는 가능한 한 원본에 가깝게 작동하도록 프로그램을 다시 작성하는 것입니다.
많은 파일 처리 중에이 프로그램을 작성한 이전 개발자는 파일을 작성해야하는 설정된 형식에 해당하는 많은 필드를 포함하는 구조를 작성하므로 모든 작업이 이미 완료되었습니다.
이 필드는 모두 바이트 배열입니다. C ++ 코드는 memset이 전체 구조를 모든 공백 문자 ( 0x20) 로 설정 하는 데 사용 됩니다 . 한 줄의 코드. 쉬운.
이 파일이 최종적으로 사용되는 유틸리티가이 형식의 파일을 기대하기 때문에 이것은 매우 중요합니다. 내가해야 할 일은이 구조체를 C #의 클래스로 변경하는 것이지만 각 바이트 배열을 모든 공백 문자로 쉽게 초기화하는 방법을 찾을 수 없습니다.
내가 끝내야했던 것은 클래스 생성자에서 이것입니다.
//Initialize all of the variables to spaces.
int index = 0;
foreach (byte b in UserCode)
{
UserCode[index] = 0x20;
index++;
}
이것은 잘 작동하지만 더 간단한 방법이 있어야합니다. 배열이 UserCode = new byte[6]생성자에서 설정 되면 바이트 배열은 자동으로 기본 null 값으로 초기화됩니다. 선언시 모든 공간이되도록 할 수있는 방법이 없어서 클래스 생성자를 호출 할 때 다음과 같이 바로 초기화됩니다. 아니면 memset비슷한 기능입니까?
작은 배열의 경우 배열 초기화 구문을 사용하십시오.
var sevenItems = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
더 큰 배열의 경우 표준 for루프를 사용하십시오 . 가장 읽기 쉽고 효율적인 방법입니다.
var sevenThousandItems = new byte[7000];
for (int i = 0; i < sevenThousandItems.Length; i++)
{
sevenThousandItems[i] = 0x20;
}
물론이 작업을 많이 수행해야하는 경우 코드를 간결하게 유지하는 데 도움이되는 도우미 메서드를 만들 수 있습니다.
byte[] sevenItems = CreateSpecialByteArray(7);
byte[] sevenThousandItems = CreateSpecialByteArray(7000);
// ...
public static byte[] CreateSpecialByteArray(int length)
{
var arr = new byte[length];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = 0x20;
}
return arr;
}
이것을 사용하여 처음에 배열을 만듭니다.
byte[] array = Enumerable.Repeat((byte)0x20, <number of elements>).ToArray();
<number of elements>원하는 배열 크기로 교체하십시오 .
Enumerable.Repeat ()를 사용할 수 있습니다
0x20으로 초기화 된 100 개 항목의 배열 :
byte[] arr1 = Enumerable.Repeat(0x20,100).ToArray();
var array = Encoding.ASCII.GetBytes(new string(' ', 100));
작은 배열을 초기화해야 할 경우 다음을 사용할 수 있습니다.
byte[] smallArray = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
더 큰 배열이 있으면 다음을 사용할 수 있습니다.
byte[] bitBiggerArray Enumerable.Repeat(0x20, 7000).ToArray();
다음 남자 / 여자가 읽을 수있는 간단하고 쉽습니다. 그리고 99.9 %의 시간이 충분할 것입니다. (일반적으로 BestOption ™이됩니다)
그러나 실제로 정말 빠른 속도가 필요한 경우 P / invoke를 사용하여 최적화 된 memset 메서드를 호출하면 다음과 같습니다.
public static class Superfast
{
[DllImport("msvcrt.dll",
EntryPoint = "memset",
CallingConvention = CallingConvention.Cdecl,
SetLastError = false)]
private static extern IntPtr MemSet(IntPtr dest, int c, int count);
//If you need super speed, calling out to M$ memset optimized method using P/invoke
public static byte[] InitByteArray(byte fillWith, int size)
{
byte[] arrayBytes = new byte[size];
GCHandle gch = GCHandle.Alloc(arrayBytes, GCHandleType.Pinned);
MemSet(gch.AddrOfPinnedObject(), fillWith, arrayBytes.Length);
return arrayBytes;
}
}
용법:
byte[] oneofManyBigArrays = Superfast.InitByteArray(0x20,700000);
아마도 이것들이 도움이 될 수 있습니까?
What is the equivalent of memset in C#?
http://techmikael.blogspot.com/2009/12/filling-array-with-default-value.html
Guys before me gave you your answer. I just want to point out your misuse of foreach loop. See, since you have to increment index standard "for loop" would be not only more compact, but also more efficient ("foreach" does many things under the hood):
for (int index = 0; index < UserCode.Length; ++index)
{
UserCode[index] = 0x20;
}
The fastest way to do this is to use the api:
bR = 0xFF;
RtlFillMemory(pBuffer, nFileLen, bR);
using a pointer to a buffer, the length to write, and the encoded byte. I think the fastest way to do it in managed code (much slower), is to create a small block of initialized bytes, then use Buffer.Blockcopy to write them to the byte array in a loop. I threw this together but haven't tested it, but you get the idea:
long size = GetFileSize(FileName);
// zero byte
const int blocksize = 1024;
// 1's array
byte[] ntemp = new byte[blocksize];
byte[] nbyte = new byte[size];
// init 1's array
for (int i = 0; i < blocksize; i++)
ntemp[i] = 0xff;
// get dimensions
int blocks = (int)(size / blocksize);
int remainder = (int)(size - (blocks * blocksize));
int count = 0;
// copy to the buffer
do
{
Buffer.BlockCopy(ntemp, 0, nbyte, blocksize * count, blocksize);
count++;
} while (count < blocks);
// copy remaining bytes
Buffer.BlockCopy(ntemp, 0, nbyte, blocksize * count, remainder);
Just to expand on my answer a neater way of doing this multiple times would probably be:
PopulateByteArray(UserCode, 0x20);
which calls:
public static void PopulateByteArray(byte[] byteArray, byte value)
{
for (int i = 0; i < byteArray.Length; i++)
{
byteArray[i] = value;
}
}
This has the advantage of a nice efficient for loop (mention to gwiazdorrr's answer) as well as a nice neat looking call if it is being used a lot. And a lot mroe at a glance readable than the enumeration one I personally think. :)
You can use a collection initializer:
UserCode = new byte[]{0x20,0x20,0x20,0x20,0x20,0x20};
This will work better than Repeat if the values are not identical.
This function is way faster than a for loop for filling an array.
The Array.Copy command is a very fast memory copy function. This function takes advantage of that by repeatedly calling the Array.Copy command and doubling the size of what we copy until the array is full.
I discuss this on my blog at http://coding.grax.com/2013/06/fast-array-fill-function-revisited.html
Note that this would be easy to make into an extension method by just adding the word "this" to the method declarations i.e. public static void ArrayFill<T>(this T[] arrayToFill ...
public static void ArrayFill<T>(T[] arrayToFill, T fillValue)
{
// if called with a single value, wrap the value in an array and call the main function
ArrayFill(arrayToFill, new T[] { fillValue });
}
public static void ArrayFill<T>(T[] arrayToFill, T[] fillValue)
{
if (fillValue.Length >= arrayToFill.Length)
{
throw new ArgumentException("fillValue array length must be smaller than length of arrayToFill");
}
// set the initial array value
Array.Copy(fillValue, arrayToFill, fillValue.Length);
int arrayToFillHalfLength = arrayToFill.Length / 2;
for (int i = fillValue.Length; i < arrayToFill.Length; i *= 2)
{
int copyLength = i;
if (i > arrayToFillHalfLength)
{
copyLength = arrayToFill.Length - i;
}
Array.Copy(arrayToFill, 0, arrayToFill, i, copyLength);
}
}
This is a faster version of the code from the post marked as the answer.
All of the benchmarks that I have performed show that a simple for loop that only contains something like an array fill is typically twice as fast if it is decrementing versus if it is incrementing.
Also, the array Length property is already passed as the parameter so it doesn't need to be retrieved from the array properties. It should also be pre-calculated and assigned to a local variable. Loop bounds calculations that involve a property accessor will re-compute the value of the bounds before each iteration of the loop.
public static byte[] CreateSpecialByteArray(int length)
{
byte[] array = new byte[length];
int len = length - 1;
for (int i = len; i >= 0; i--)
{
array[i] = 0x20;
}
return array;
}
You could speed up the initialization and simplify the code by using the the Parallel class (.NET 4 and newer):
public static void PopulateByteArray(byte[] byteArray, byte value)
{
Parallel.For(0, byteArray.Length, i => byteArray[i] = value);
}
Of course you can create the array at the same time:
public static byte[] CreateSpecialByteArray(int length, byte value)
{
var byteArray = new byte[length];
Parallel.For(0, length, i => byteArray[i] = value);
return byteArray;
}
'IT' 카테고리의 다른 글
| Javascript를 사용하여 jquery 가로 드되었는지 확인 (0) | 2020.06.12 |
|---|---|
| 명령 줄을 사용하여 JSON 객체의 항목을 계산하는 방법은 무엇입니까? (0) | 2020.06.12 |
| 부울 검사에 xor 연산자를 사용하는 것이 좋습니다? (0) | 2020.06.12 |
| Java 응용 프로그램 내부에서 VM 인수를 얻는 방법은 무엇입니까? (0) | 2020.06.12 |
| CSS에서 최대 문자 길이 설정 (0) | 2020.06.12 |

