문제

나는이 작은 Helloworld를 후속 조치로 쓰고 있습니다 이것 그리고 숫자는 합산되지 않습니다

filename = "testThis.txt"
total_bytes = 0
file = File.new(filename, "r")
file.each do |line|
  total_bytes += line.unpack("U*").length
end
puts "original size #{File.size(filename)}"
puts "Total bytes #{total_bytes}"

결과는 파일 크기와 동일하지 않습니다. 나는 단지 무엇을 알아야한다고 생각합니다 format 플러그를 꽂아야합니다 ... 또는 어쩌면 포인트를 완전히 놓쳤을 수도 있습니다. 파일 크기를 라인별로 측정하려면 어떻게해야합니까?

참고 : 나는 Windows에 있고 파일은 ANSI 유형으로 인코딩됩니다.

편집하다: 이것은 동일한 결과를 생성합니다!

filename = "testThis.txt"
total_bytes = 0
file = File.new(filename, "r")
file.each_byte do |whatever|
  total_bytes += 1
end
puts "Original size #{File.size(filename)}"
puts "Total bytes #{total_bytes}"

그래서 지금 도울 수있는 사람은 누구나 ...

도움이 되었습니까?

해결책

IO#은 명령 줄에서 입력을 캡처하는 것과 동일하게 작동합니다. "ENTER"는 입력의 일부로 전송되지 않습니다. #gets가 파일 또는 IO의 다른 서브 클래스에서 호출 될 때 전달되지 않으므로 숫자는 확실히 일치하지 않을 것입니다.

관련성을 참조하십시오 PICAXE 섹션

파일 크기에 합계 라인 길이에 대해 왜 그렇게 걱정하는지 문의해도 될까요? 필요한 것보다 더 어려운 문제를 해결할 수 있습니다 ...

아하. 나는 지금 그것을 얻는 것 같아요.

편리한 iPod (또는 그 문제에 대해 다른 종류)이 없으면 정확히 4K 덩어리를 원합니다 라인을 깨는 것이 더 행복하며,이 경우에는 다음과 같은 것이 작동해야합니다.

class Chunkifier
  def Chunkifier.to_chunks(path)
    chunks, current_chunk_size = [""], 0
    File.readlines(path).each do |line|
      line.chomp! # strips off \n, \r or \r\n depending on OS
      if chunks.last.size + line.size >= 4_000 # 4096?
        chunks.last.chomp! # remove last line terminator
        chunks << ""
      end
      chunks.last << line + "\n" # or whatever terminator you need
    end
    chunks
  end
end

if __FILE__ == $0
  require 'test/unit'
  class TestFile < Test::Unit::TestCase
    def test_chunking
      chs = Chunkifier.to_chunks(PATH)
      chs.each do |chunk|
        assert 4_000 >= chunk.size, "chunk is #{chunk.size} bytes long"
      end
    end
  end
end

io #readlines를 사용하여 모든 텍스트를 하나의 슬러프로 가져옵니다. #Each 또는 #Each_Line도 마찬가지입니다. 나는 String#chomp를 사용했습니다! OS가 수행하는 모든 일을 보장하기 위해 마지막의 BYT가 제거되므로 n 또는 출력으로 강제 할 수 있습니다.

후자는 OS 특정 Newline 시퀀스를 제공하는 경향이 있기 때문에 출력에 대한 #print 또는 #puts 대신 파일 #쓰기를 사용하는 것이 좋습니다.

멀티 바이트 캐릭터에 대해 걱정하는 경우 각 _byte 또는 포장 풀 (C*) 옵션 및 원숭이 패치 문자열을 사용하는 것을 고려하십시오.

class String
  def size_in_bytes
    self.unpack("C*").size
  end
end

포장 풀기 버전은 내 컴퓨터의 eary_byte 1보다 약 8 배 빠릅니다. BTW.

다른 팁

io#earg_byte, 예를 들어 시도 할 수 있습니다

total_bytes = 0
file_name = "test_this.txt"
File.open(file_name, "r") do |file|
  file.each_byte {|b| total_bytes += 1}
end
puts "Original size #{File.size(file_name)}"
puts "Total bytes #{total_bytes}"

물론 그것은 한 번에 당신에게 줄을주지 않습니다. 그것에 대한 최선의 선택은 아마도 파일을 통해 파일을 통과하는 것입니다. each_byte 만날 때까지 \r\n. IO 클래스는 도움이 될 수있는 매우 낮은 수준의 읽기 방법을 제공합니다.

여기에는 몇 가지 중복 문제가 있습니다.

  1. 라인 피드 캐릭터 \r\n vs. \n (이전 게시물에 따라). 또한 파일 문자 (^z)?

  2. 문제 문서에서 "크기"의 정의 : "얼마나 많은 문자"(다중 바이트 문자 인코딩을 고려한)를 의미합니까?

  3. 상호 작용 $KCODE 글로벌 변수 (루비 1.9에서 더 이상 사용되지 않습니다. 참조 String#encoding 그리고 당신이 1.9 세 미만을 달리는 경우 친구. 예를 들어 파일에 악센트가있는 문자가 있습니까?

  4. 당신의 형식 문자열 #unpack. 나는 당신이 원한다고 생각합니다 C* 바이트를 실제로 계산하고 싶다면 여기에 있습니다.

또한 존재에 주목하십시오 IO#each_line (그냥 버릴 수 있습니다 while 그리고 조금 더 루비 아이디어가 되십시오 ;-)).

문제는 Windows에 텍스트 파일을 저장할 때 라인 브레이크가 두 문자 (문자 13 및 10)이므로 2 바이트가되므로 Linux에 저장하면 1 (문자 10) 만 있습니다. 그러나 루비는 이것을 단일 문자 ' n'으로보고합니다. 문자 10이라고합니다.

그래서, 당신이 알다 파일이 항상 Windows 텍스트 파일에서 나오고 Windows에서 실행되며 Newline 문자를 얻을 때마다 카운트에 1을 추가 할 수 있습니다. 그렇지 않으면 몇 가지 조건부와 작은 상태 기계입니다.

btw '문자'가 없습니다.

f = File.new("log.txt")
begin
    while (line = f.readline)
        line.chomp
        puts line.length
    end
rescue EOFError
    f.close
end

다음은 현재 파일 포인터가 읽기 파일에서 줄의 시작으로 설정되었다고 가정하는 간단한 솔루션입니다.

    last_pos = file.pos
    next_line = file.gets
    current_pos = file.pos
    backup_dist = last_pos - current_pos
    file.seek(backup_dist, IO::SEEK_CUR)

이 예에서 "파일"은 읽는 파일입니다. 루프에서 이것을하기 위해 :

    last_pos = file.pos
    begin loop
        next_line = file.gets
        current_pos = file.pos
        backup_dist = last_pos - current_pos
        last_pos = current_pos
        file.seek(backup_dist, IO::SEEK_CUR)
    end loop
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top