![]() |
![]() HP OpenVMS Systemsask the wizard |
![]() |
The Question is: I have a third party file that has compressed data starting at byte 114 of a 485 byte record. Byte 1 thru 113 is ascii. Is there a VMS command to unparse the data and convert/write it to a sequential file? The Answer is : Without knowing what sort of data compression scheme is used, this question is difficult to answer. Opening and reading an RMS file is trivial, the code to perform the decompression depends on the algorithm used. Attached is C code that opens an RMS file, and displays the records of the file to the terminal. Several changes -- support for a longer record length, and the decompression scheme, obviously -- would need to be made to this example for your particular application. /* ** COPYRIGHT (c) 1992 BY ** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS. ** ALL RIGHTS RESERVED. ** ** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ** ONLY IN ACCORDANCE OF THE TERMS OF SUCH LICENSE AND WITH THE ** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY ** OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ** TRANSFERRED. ** ** THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ** AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ** CORPORATION. ** ** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. */ /* **++ ** Facility: ** ** Examples ** ** Version: V1.1 ** ** Abstract: ** ** Example of working with RMS calls from C ** ** Author: ** Steve Hoffman (XDELTA::HOFFMAN) ** ** Creation Date: 1-Jan-1990 ** ** Modification History: ** Hoffman 15-Oct-1994 Updates for DEC C **-- */ /* // RMS_EXAMPLES.C // // Program displays some RMS calls made from the c language. Types out // the calling process's SYS$LOGIN:LOGIN.COM file to SYS$OUTPUT. // // Included is a main and three subroutines. The subroutines open, // read a record, and close the file. Several hooks, such as the // use of the NAM block to obtain the specification of the file that // was actually opened, are included but are not currently used. // // To build: // // $ CC [/DECC] [/DEBUG/NOOPTIM] RMS_EXAMPLES // $ LINK [/DEBUG] RMS_EXAMPLES // $ RUN [/[NO]DEBUG] RMS_EXAMPLES */ #include <lib$routines.h> #include <rms.h> #include <starlet.h> #include <string.h> #include <ssdef.h> #include <stdio.h> #include <stsdef.h> /* // RMS_MRS is the maximum record size that can be read (and thus // displayed) by this program. */ #define RMS_MRS 255 /* // The following is the core data structure for the program. // The various RMS subroutines all communicate via a pointer // referencing this struct. */ struct RmsFileContext { struct FAB fab; struct RAB rab; struct NAM nam; char rss[NAM$C_MAXRSS]; short max_rec_siz; char *data_buffer; }; RmsFileOpen( void **CtxArg, char *FileName, char *DefFileName, int flags, int rss ) { int RetStat; struct RmsFileContext *Ctx; int howbig = sizeof( struct RmsFileContext ); /* // acquire some space for a Context block. */ RetStat = lib$get_vm( &howbig, &Ctx, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; *CtxArg = (void *) Ctx; /* // Fill in the various fields of the Context block. // -- Builds the File Access Block (FAB), the Record Access // Block (RAB) and the Name (NAM) Block. Along with some // other miscellaneous housekeeping stuff. */ Ctx->fab = cc$rms_fab; Ctx->rab = cc$rms_rab; Ctx->nam = cc$rms_nam; Ctx->fab.fab$l_nam = &Ctx->nam; Ctx->fab.fab$l_fop = FAB$M_NAM; Ctx->fab.fab$b_fac = FAB$M_GET; Ctx->fab.fab$l_fna = FileName; Ctx->fab.fab$b_fns = strlen( FileName ); Ctx->fab.fab$l_dna = DefFileName; Ctx->fab.fab$b_dns = strlen( DefFileName ); Ctx->rab.rab$l_fab = &Ctx->fab; Ctx->nam.nam$b_rss = NAM$C_MAXRSS; Ctx->nam.nam$l_rsa = Ctx->rss; Ctx->rab.rab$b_rac = RAB$C_SEQ; /* // Attempt to open the file... */ RetStat = sys$open( &Ctx->fab, 0, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; /* // Allocate a buffer large enough for the biggest record. */ RetStat = lib$get_vm( &RMS_MRS, &Ctx->data_buffer, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; /* // Attempt to connect the record stream to the file... */ RetStat = sys$connect( &Ctx->rab, 0, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; return RetStat; } RmsFileRead( void **CtxArg, char **BufAdr, int *BufLen ) { int RetStat; struct RmsFileContext *Ctx = *CtxArg; Ctx->rab.rab$l_ubf = Ctx->data_buffer; Ctx->rab.rab$w_usz = RMS_MRS; RetStat = sys$get( &Ctx->rab, 0, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) { *BufLen = (char) 0; *BufAdr = (char) 0; return RetStat; } *BufAdr = Ctx->rab.rab$l_rbf; *BufLen = Ctx->rab.rab$w_rsz; return RetStat; } RmsFileClose( void **CtxArg ) { int RetStat; struct RmsFileContext *Ctx = *CtxArg; /* // Free up the record buffer... */ RetStat = lib$free_vm( &RMS_MRS, &Ctx->data_buffer, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; /* // Be nice and clean up the record stream... */ RetStat = sys$disconnect( &Ctx->rab, 0, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; /* // And close the file... */ RetStat = sys$close( &Ctx->fab, 0, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; /* // And free up the allocated memory... */ RetStat = lib$free_vm( &sizeof( struct RmsFileContext ), CtxArg, 0 ); if ( !$VMS_STATUS_SUCCESS( RetStat ) ) return RetStat; return RetStat; } main() { int RetStat; void *Context; char *BufAdr; int BufLen; /* // Open the file. Minimal checking is performed. Read access only. */ RetStat = RmsFileOpen( &Context, "LOGIN", "SYS$LOGIN:.COM", 0, 0 ); /* // Read the file. Minimal checking is performed. */ for (;;) { RetStat = RmsFileRead( &Context, &BufAdr, &BufLen ); if ( $VMS_STATUS_SUCCESS( RetStat ) ) printf("%*.*s\n", BufLen, BufLen, BufAdr ); else break; } /* // Close up shop. */ RetStat = RmsFileClose( &Context ); return RetStat; }
|