2010-02-05 3 views
3

Storable의 store_fd를 사용하고 fd_retrieve를 사용하면 데이터 구조를 프로그램의 DATA 파일 핸들에 저장할 수 있는지 궁금했습니다. 나는 이것이 베스트 프랙티스가 아니라는 것을 알고있다, 그것이 효과가 있다면 나는 단지 궁금해서, 그것을 시도하려는 나의 빠른 시도는 효과가없는 것처럼 보인다.DATA 파일 핸들에 저장할 수 있습니까?

+0

저는 fd_retreive가 작동하고 store_fd가 실패 할 것으로 예상합니다. –

+0

당신은 무엇을 염두에 두 고 있습니까? –

+1

DATA는 일반적으로 입력 용으로 만 열 수 있습니다. 인라인 :: 파일을 사용해 보시겠습니까? – ysth

답변

2

왜 그렇게하고 싶은지 잘 모르겠지만 위조 할 수는 있습니다. 당신은 그것을 피하려고 노력해야한다.

킥킥 웃음을 위해 파일 핸들을 열고 $0의 행을 읽고 __DATA__에 도달 할 때까지 인쇄 한 다음 새로운 __DATA__ 섹션을 추가 할 수 있습니다. 그것은 일반적인 조건에서 불가능

#!perl 

my $mode = (stat($0))[2] & 07777; 

open my($fh), '<', $0 or die "I can't open me! $!\n"; 
open my($new), '>', "$0.new" or die "I can't open you! $!\n"; 
eval { chmod($mode, $new) } or warn "Couldn't set permissions: [email protected]\n"; 

while(<$fh>) 
    { 
    last if /^__DATA__$/; 
    print { $new } $_; 
    } 

print "I am $$\n"; 
print { $new } "__DATA__\n", join '|', $$, time, (stat($0))[1]; 

rename("$0.new", $0) 

__DATA__ 
64574|1265415126|8843292 
1

DATA의 핸들이며 스크립트로 저장된 데이터를 읽습니다. Conway의 Inline::Files쓰기 가능한 가상 파일에 대해 내가 아는 유일한 모듈입니다. 그리고 스크립트 파일은 대개 ASCII이므로 MSDOS에서 2 진수 26 바이트를 얻었거나 UNIX에서 Storable 출력에서 ​​2 진수 4를 얻으면 어떤 결과가 발생할지 모릅니다. 당신이 거기에를 입력 하여 데이터를 저장 에 대해 이야기하는 경우

그러나 만에 은 바이너리 문제가 여전히 직면, 스크립트에서에게 그것을 읽어보십시오.

따라서 지속성을 위해 YAML 또는 JSON으로가는 것이 좋습니다. YAML이 DATA에서 데이터를 검색 할 때 축복을 처리한다는 것을 알고 있습니다.

+0

'binmode (__ DATA __)'나는 상상한다. –

1

:

$ cat write-data 
#! /usr/bin/perl 

use warnings; 
print DATA "bar!\n"; 

$ ./write-data 
Name "main::DATA" used only once: possible typo at ./write-data line 6. 
print() on unopened filehandle DATA at ./write-data line 6.

시스템이 프로그램이 실행되는 동안 파일을 잠그는 경우 트릭은 아마도 exec에 의해, $0가 될 새 파일의 이름을 변경하는 것입니다

그러나 사용자가 만들 수있는 특별한 조건 :

#! /usr/bin/perl 

use warnings; 
use strict; 

use Data::Dumper; 
use File::Temp qw/ tempfile /; 
use Storable qw/ store_fd fd_retrieve /; 

sub store_in_DATA { 
    my($data) = @_; 

    my($fh,$path) = tempfile; 
    unlink $path   or warn "$0: unlink: $!"; 

    *DATA = $fh; 
    store_fd $data, \*DATA or warn "$0: print: $!"; 

    seek DATA, 0, 0  or warn "$0: seek: $!"; 
} 

store_in_DATA { foo => "There is no spoon.\n" }; 

undef $/; 
my $ref = fd_retrieve \*DATA; 
print Dumper $ref; 

Windows에서 기본 파일 공유 의미론으로 인해 unlink에 대한 경고가 표시됩니다. 이것이 플랫폼 인 경우 END 시간을 정리하거나 Win32::SharedFileOpen을 사용할 수 있습니다.

0

나는 내 자신의 해결책을 생각해 냈다 ... 나는 특별히 그것을 추천하지 않았다. 제 경우에는 다차원 해시 구조의 참조 값을 가진 단위 테스트 스크립트입니다. 이 작업이 수행하는 작업과 그 이유에 대한 기술적 인 내용은 다루지 않겠지 만 코드의 작은 수정이나 변경으로 인해 많은 값이 업데이트 될 수 있습니다 (변경 유효성을 확인한 후).

따라서 Data::Dumper을 사용하여 __DATA__ 섹션으로 해시를 이동했습니다. 나는에 mtime은 파일 hasn를 확인하는 데 사용됩니다 (초기 핸들의 위치와 mtime에 대한 참조를 저장 한 후 DATA에서 해시를로드

use Data::Dumper; 
$Data::Dumper::Terse = 1; # to Eval whole thing as a hash 
$Data::Dumper::Indent = 1; # Looks better, just a preference 
$Data::Dumper::Sortkeys = 1; # To keep changes minimal in source control 
print $fh Dumper(\%HASH); 

스크립트의 시작 부분에서 : 같은 파일 핸들의 모양에 코드는 쓰기 스크립트가 실행되는 동안 수정되었습니다.)마지막으로

use vars qw(%HASH $FILEPOS $MTIME); 

{ 
    $FILEPOS = tell(DATA); 
    $MTIME = (stat(DATA))[9]; 
    local $/; 
    my $data = <DATA>; 
    %HASH = %{eval $data}; 
} 

, 나는 $FILEPOS__FILE__를 열 __DATA__ 섹션을 업데이트하기 위해, 그것을 잘라 그것을 쓰기. 나는이 예제에 대한 오류 처리를 단순화했다.

open(my $fh, '>>', __FILE__) or die $!; 
seek($fh, $FILEPOS, 0) or die $!; 
die "File changed" if ((stat($fh))[9] != $MTIME); 
truncate($fh, $FILEPOS) or die $!; 

# Assumes Dumper is already loaded and configured as in first code snippet 
print $fh Dumper(\%HASH); 

실수로 파일을 백업 할 때 실수로 코드가 손상 될 수 있습니다.

Storable과 동일하게 작동합니다. 스토리지가 더 효율적이고 빠릅니다. 유일한주의 사항은 바이너리라는 점입니다. 즉, diff 파일이 소스 컨트롤에 표시되지 않고 Dumper의 출력으로 편집하기가 쉽지 않음을 의미합니다.

관련 문제