2010-03-19 3 views
11

매번 파일 스트림이나 파일 구조에 '1 비트'를 쓸 수 있습니까? 큐에 쓰고 플러시 할 수 있습니까? C# 또는 Java로 가능합니까? 허프만 코드 작성의 인스턴스를 구현하려고 할 때 필요했습니다. 나는 파일에 비트를 쓸 수 없다. 그래서 그들을 비트셋에 쓰고 (압축이 끝나면) 매번 8 비트 조각을 씁니다 (마지막 하나는 제외). 당신이 전체 바이트를 축적 할 때까지 각각의 비트를 버퍼링'비트'를 C++ 파일 스트림에 작성

+0

어떤 언어를 놓치셨습니까? 대부분의 언어는 한 번에 1 바이트 미만을 쓸 수 없습니다. 개별 비트를 테스트하고 결과를 인쇄 할 수 있습니다. – dirkgently

답변

13

좋은 생각처럼 보인다 :

byte b; 
int s; 

void WriteBit(bool x) 
{ 
    b |= (x ? 1 : 0) << s; 
    s++; 

    if (s == 8) 
    { 
     WriteByte(b); 
     b = 0; 
     s = 0; 
    } 
} 

당신 기록 할 비트 수의 배수가 아닌 경우 단지의 경우 처리해야 여덟.

+0

좋아 보인다. 마지막 경우는'bool flush' 인자와'if (s == 8 || flush)'테스트로 처리 할 수 ​​있습니다. –

+0

그냥 s가 0으로 초기화되었는지 확인하십시오. –

+1

바이트 내의 "첫 번째"또는 "마지막"비트가 C 표준에서 정의되거나 함축되어 있지 않으며 단지 대부분의 또는 최소한의 중요도를 가지며 "왼쪽"및 "오른쪽"을 그것은 교대와 관련이있다. 따라서 WriteBit은 비트가 가장 많이 쓰여지는지 아니면 가장 중요하지 않은지를 먼저 결정해야합니다. 당신은 최소한의 의미를 지키며 간다. 위키피디아는 직렬 통신을위한 하드웨어 수준에서 가장 많이 사용된다고 주장한다. 필자는 필자 자신을 알기 위해 시리얼 드라이버를 충분히 깊이 생각하지 못했습니다. –

3

어떤 파일 시스템을 사용하고 있습니까?

대부분의 경우 파일 길이를 바이트로 저장합니다 (이 있습니까?). 따라서 전체 바이트 수가 아닌 실제 파일을 가질 수 없습니다.

비트 스트림으로 파일에 쓰는 경우 작업이 끝나면 마지막 몇 비트를 자르거나 나머지 비트에 정크로 채우는 양으로 최종 바이트를 작성해야합니다.

다음은

class BitFile(file): 
    def __init__(self, filename, mode): 
     super(BitFile, self).__init__(filename, mode) 
     self.bitCount=0 
     self.byte = 0 

    def write(self, bit): 
     self.bitCount+=1 
     self.byte = self.byte*2+bit 
     if self.bitCount%8==0: 
      super(BitFile, self).write(chr(self.byte)) 
      self.byte=0 

    def close(self): 
     if self.bitCount%8!=0: 
      super(BitFile, self).write(chr(self.byte)) 
     super(BitFile, self).close()  

with BitFile("bitfile.bin","w") as bf: 
    bf.write(1) 
    bf.write(1) 
    bf.write(1) 
    bf.write(0) 
    bf.write(0) 
    bf.write(0) 
    bf.write(0) 
    bf.write(0) 
    bf.write(1) 
0

당신은 정말 할 수 없습니다를 시작하는 데 몇 가지 파이썬 코드입니다. 나는 문제가 언어 나 파일 시스템이 아니라 하드웨어 문제라고 확신한다. 프로세서는 바이트와 함께 작동하도록 설계되었습니다. 당신이 할 수있는 가장 가까운 방법은 마지막 바이트를 반복해서 쓰는 것입니다. 한 번에 하나씩 변경하면서 0으로 채워집니다.

그래서 비트 '가 11011', 다음 (파이썬 예를 할 수있는 쓰기,하지만 어떤 언어는이 작업을 수행하는 시설이 있어야합니다

당신은 성능 향상의 일종을 얻을 수 있었으면되지 않은

f.write(chr(0b10000000)) 
f.flush() 
f.seek(-1) 
f.write(chr(0b11000000)) 
f.flush() 
f.seek(-1) 
f.write(chr(0b11000000)) 
f.flush() 
f.seek(-1) 
f.write(chr(0b11010000)) 
f.flush() 
f.seek(-1) 
f.write(chr(0b11011000)) 
f.flush() 
이 당신을했다? 내가 오히려 큰 버퍼 (4096 바이트 이상)을 할당하는 것이 좋습니다과가 가득 할 때마다 디스크에 저를 세척하십시오. 1 바이트 버퍼는 일반적으로 나쁜 성능을 유발 사용 할

+0

참고로 C 및 C++ 언어에는 2 진 상수를 선언 할 수있는 기능이 없습니다. –

0

.

+0

otf arabic의 글리프 pos 데이터와 같이 거대한 파일을 압축하려고합니다. copmressing이 29MB 인 경우 크기는 48MB입니다. 그래서 당신의 방법은 이론적이지 않습니다. 메모리를 낭비합니다. –

+1

당신은 내 방법을 오해했습니다. 나는 단순히 바이트보다 큰 버퍼를 제안하고, 플러시가 훨씬 덜 빈번하게 수행되며, 전체 데이터를 저장하는 버퍼는 아닙니다. – Tronic

0

I 허프 먼 해독을 위해 이것을 한 번하고 결국 끝냈다. 비트를 문자로 작성하여 모든 것을 내부적으로 오래된 C 문자열로 처리합니다.

그런 식으로 후행 바이트에 대해 걱정할 필요가 없으며 사람이 읽을 수 있습니다. 또한 비트 검사는 문자 배열 (binbuf[123] == '1')을 처리하는 대신 비트를 사용하는 것보다 쉽습니다. 가장 최적화 된 솔루션이 아니라 내 문제를 깔끔하게 해결했습니다.

명백한 단점은이 표현이 더 많은 메모리를 사용한다는 것입니다.

8

당신은 간결한 방식으로 원하는 결과를 달성하기 std::ostream_iterator 함께 boost::dynamic_bitset을 사용할 수

#include <fstream> 
#include <iterator> 
#include <boost/dynamic_bitset.hpp> 

typedef boost::dynamic_bitset<unsigned char> Bitset; 

// To help populate the bitset with literals */ 
Bitset& operator<<(Bitset& lhs, bool val) {lhs.push_back(val); return lhs;} 

int main() 
{ 
    Bitset bitset; 
    bitset<<0<<1<<0<<1<<0<<1<<0<<1 
      <<1<<0<<1<<0; 

    std::ofstream os("data.dat", std::ios::binary); 
    std::ostream_iterator<char> osit(os); 
    boost::to_block_range(bitset, osit); 

    return 0; 
} 

는 I 템플릿 파라미터로서 unsigned char를 지정하여 제 dynamic_bitset 8 비트의 블록 크기를 만들었다.더 큰 정수 유형을 지정하여 블록 크기를 크게 만들 수 있습니다.

boost::to_block_range은 블록의 비트 세트를 지정된 출력 반복기에 덤프합니다. 마지막 블록에 빈 나머지 비트가 있으면 0으로 채워집니다.

16 진수 편집기에서 data.dat을 열면 AA 05이 표시됩니다. 이것은 리틀 엔디안 플랫폼 (x64)에 있습니다.

0

여기에있는 문제는 많은 플랫폼이 직접 비트 액세스 권한이 없다는 것입니다. 비트를 최소 패키지로 그룹화합니다. 종종 바이트 또는 워드 번을 사용합니다. 또한, 스트림 장치에 대한 프로토콜은 개별 비트의 전송을 용이하게하지 못한다.

개별 비트를 처리하는 일반적인 방법은 액세스 가능한 가장 작은 휴대용 및 (주소 지정 가능한) 장치에 포장하는 것입니다. 사용되지 않는 비트는 일반적으로 0으로 설정됩니다. 이것은 2 진 산술 연산 (OR, AND, EXCLUSIVE-OR, NOT 등)으로 수행 할 수 있습니다.

최신 프로세서의 경우 비트 왜곡으로 인해 컴퓨터와 성능이 느려집니다. 메모리는 저렴하고 큰 주소 공간이있어 비트 패킹에 대한 정당성이 더욱 어려워졌습니다. 일반적으로 비트 패킹은 하드웨어 지향 연산 (및 전송 프로토콜)을 위해 예약되어 있습니다. 예를 들어 프로세서의 워드의 용량이 16 비트 인 경우 프로세서는 한 단어로 16 비트보다 16 비트 빠른 처리를 처리 할 수 ​​있습니다.

또한 메모리에서 쓰거나 메모리에서 쓰는 것이 스트림의 I/O보다 빠르다는 점에 유의하십시오. 효율적인 시스템은 데이터를 전송하기 전에 메모리에 데이터를 버퍼링합니다. 당신은 당신의 디자인에서이 기술을 고려하고 싶을지도 모른다. I/O 작업을 줄이면 프로그램 성능이 향상됩니다.