루비에서 바이너리 파일을 문자열로 읽기


263

tar 파일을 가져 와서 문자열로 변환하거나 그 반대로 변환하는 쉬운 방법이 필요합니다. Ruby에서이를 수행 할 수있는 방법이 있습니까? 최선의 시도는 다음과 같습니다.

file = File.open("path-to-file.tar.gz")
contents = ""
file.each {|line|
  contents << line
}

문자열로 변환하기에 충분하다고 생각했지만 다음과 같이 다시 쓰려고하면 ...

newFile = File.open("test.tar.gz", "w")
newFile.write(contents)

같은 파일이 아닙니다. 이렇게하면 ls -l파일 크기가 매우 비슷하지만 파일을 열면 대부분의 내용이 그대로 표시됩니다. 내가 저지르는 작은 실수 나 이것을 달성하는 완전히 다른 (그러나 실행 가능한) 방법이 있습니까?


3
압축 된 tar 파일입니다. "라인"이 없습니다. Pls는 당신이 달성하려는 것을 분명히합니다.
Brent. Longborough

압축 된 데이터 또는 압축되지 않은 컨텐츠를 보려고합니까?
David Nehme

그래서 압축 된 데이터 스트림의 문자는 대략 1 256에서 착륙의 기회 "\ n"을 가지고 너무, 내 대답은 아래를 참조하십시오 "\ 연구를"줄의 끝을 정의하고, 예상하지 않는 경우 그 괜찮아요
Purfideas

이 질문은 " 이진 파일을 문자열로 변환"으로 제목을 변경해야합니다 IO.read. 그렇지 않으면 선호되는 답변이 될 것입니다.
Ian

답변:


397

먼저 파일을 이진 파일로 열어야합니다. 그런 다음 하나의 명령으로 전체 파일을 읽을 수 있습니다.

file = File.open("path-to-file.tar.gz", "rb")
contents = file.read

그러면 전체 파일이 문자열로 표시됩니다.

그 후에는 아마도을 원할 것 file.close입니다. 그렇게하지 않으면 file가비지 수집 될 때까지 닫히지 않으므로 열려있는 동안 시스템 리소스가 약간 낭비됩니다.


22
이진 플래그는 Windows에서만 관련이 있으며 파일 설명자를 열어 둡니다. File.read (...)가 더 좋습니다.
Daniel Huckstep

너무 많은 사람들이 이것을 찾아서 하나의 라이너 솔루션으로 붙여 넣는 데 문제가 있습니까 (스택 오버 플로우의 많은 것들)? 결국, 그것은 작동하며, 이러한 기능의 이름은 루비 라이브러리 디자이너가 임의로 선택했습니다. 우리가 동의어가있는 언어 만 가지고 있다면 ... 어쨌든 우연한 경우 / 모호한 인스턴스에서 원하는 것을 정확히 알고 있습니다. 그럼 난 그냥 contents = (contents of file "path to file.txt" as string).
masterxilo

2
이것은에서 수행되어야한다 begin {..open..} ensure {..close..} end블록
shadowbq의

3
@ArianFaurtosh 아니요, 파일을 읽는 또 다른 방법입니다. 실행 파일로 취급되어 실행된다는 의미는 아닙니다! 그것은 간단한 '읽기'방법에 ​​대한 끔찍한 부작용입니다.
Matthew 읽기

1
@David는 단순히 다음의 한 줄짜리를 할 수 없었습니까? apidock을contents = File.binread('path-to-file.tar.gz') 참조하십시오 . 의 하위 클래스입니다 . FileIO
vas

244

이진 모드가 필요한 경우 어려운 방법으로 수행해야합니다.

s = File.open(filename, 'rb') { |f| f.read }

그렇지 않으면 짧고 감미로운 것입니다 :

s = IO.read(filename)

루비 1.9.3 이상에서 IO.read는 Encoding.default_external에 인코딩으로 표시된 문자열을 제공합니다. 나는 (?) 바이트가 파일에있는 그대로있을 것이라고 생각 하므로 정확하게 "이진 안전하지 않음"은 아니지만 원하는 경우 이진 인코딩으로 태그를 지정해야합니다.
jrochkind

곤란과 단맛이 본질 인 경우, 앰퍼샌드 심볼 PROC 트릭 제공s = File.open(filename, 'rb', &:read)
Epigene

114

파일을 열어 두지 않으려면 File.open에 블록을 전달하는 것이 가장 좋습니다. 이런 식으로, 블록이 실행 된 후 파일이 닫힙니다.

contents = File.open('path-to-file.tar.gz', 'rb') { |f| f.read }

10
파일 디스크립터는 유한 한 시스템 자원이고이를 소진하는 것은 쉽게 피할 수있는 일반적인 문제이기 때문에 David Nehme보다 더 나은 대답입니다.
Jeff McCune

17

os x에서 이것들은 나에게 동일합니다 ... 이것은 Windows에서 여분의 "\ r"일 수 있습니까?

어쨌든 당신은 다음과 같이 더 나을 수 있습니다.

contents = File.read("e.tgz")
newFile = File.open("ee.tgz", "w")
newFile.write(contents)

이것은 가장 간단한 해결책처럼 보입니다.
Dishcandanty

17

어떤 개방 / 폐쇄 안전은 어떻습니까?

string = File.open('file.txt', 'rb') { |file| file.read }

왜 명시 .close가 아닌가? OP 파일에서와 같이 완료되면 닫힙니 까?
Joshua

2
File.open () {| file | block}은 블록이 종료되면 자동으로 닫힙니다. ruby-doc.org/core-1.9.3/File.html#method-c-open
Alex

14
이것은 2008 년에 게시 된 Aaron Hinni의 답변 과 동일합니다 (OP의 파일 및 변수 이름을 사용하지 않는 것 제외).
Abe Voelker

10

루비는 이진 읽기

data = IO.binread(path/filaname)

또는 Ruby 1.9.2보다 작은 경우

data = IO.read(path/file)

7

tar 파일을 Base64로 인코딩 할 수 있습니다. Base 64는 일반 텍스트 파일로 저장할 수있는 파일의 순수한 ASCII 표현을 제공합니다. 그런 다음 텍스트를 다시 디코딩하여 tar 파일을 검색 할 수 있습니다.

당신은 다음과 같은 일을합니다 :

require 'base64'

file_contents = Base64.encode64(tar_file_data)

더 나은 아이디어를 얻으려면 Base64 Rubydocs 를 살펴보십시오 .


좋아, 이것도 작동하는 것처럼 보입니다! 어떤 이유로 바이너리 내용을 읽는 것이 어려워지면 확인해야합니다.
Chris Bunch

0

Base64로 tar 파일을 인코딩하고 일반 텍스트 파일로 저장하면 다음을 사용할 수 있습니다

File.open("my_tar.txt").each {|line| puts line}

또는

File.new("name_file.txt", "r").each {|line| puts line}

cmd에서 각 (텍스트) 줄을 인쇄하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.