1 /******************************************************************************
2  * $Id: dbfdump.c,v 1.14 2016-12-05 12:44:05 erouault Exp $
3  *
4  * Project:  Shapelib
5  * Purpose:  Sample application for dumping .dbf files to the terminal.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 1999, Frank Warmerdam
10  *
11  * This software is available under the following "MIT Style" license,
12  * or at the option of the licensee under the LGPL (see COPYING).  This
13  * option is discussed in more detail in shapelib.html.
14  *
15  * --
16  *
17  * Permission is hereby granted, free of charge, to any person obtaining a
18  * copy of this software and associated documentation files (the "Software"),
19  * to deal in the Software without restriction, including without limitation
20  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21  * and/or sell copies of the Software, and to permit persons to whom the
22  * Software is furnished to do so, subject to the following conditions:
23  *
24  * The above copyright notice and this permission notice shall be included
25  * in all copies or substantial portions of the Software.
26  *
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33  * DEALINGS IN THE SOFTWARE.
34  ******************************************************************************
35  *
36  * $Log: dbfdump.c,v $
37  * Revision 1.14  2016-12-05 12:44:05  erouault
38  * * Major overhaul of Makefile build system to use autoconf/automake.
39  *
40  * * Warning fixes in contrib/
41  *
42  * Revision 1.13  2013-11-26 21:52:33  fwarmerdam
43  * report deleted rows in dbfdump
44  *
45  * Revision 1.12  2006-06-17 00:15:08  fwarmerdam
46  * Free panWidth for better memory testing.
47  *
48  * Revision 1.11  2006/02/15 01:11:27  fwarmerdam
49  * added reporting of native type
50  *
51  * Revision 1.10  2004/09/26 20:09:35  fwarmerdam
52  * avoid rcsid warnings
53  *
54  * Revision 1.9  2002/01/15 14:36:07  warmerda
55  * updated email address
56  *
57  * Revision 1.8  2001/05/31 18:15:40  warmerda
58  * Added support for NULL fields in DBF files
59  *
60  * Revision 1.7  2000/09/20 13:13:55  warmerda
61  * added break after default:
62  *
63  * Revision 1.6  2000/07/07 13:39:45  warmerda
64  * removed unused variables, and added system include files
65  *
66  * Revision 1.5  1999/11/05 14:12:04  warmerda
67  * updated license terms
68  *
69  * Revision 1.4  1998/12/31 15:30:13  warmerda
70  * Added -m, -r, and -h commandline options.
71  *
72  * Revision 1.3  1995/10/21 03:15:01  warmerda
73  * Changed to use binary file access.
74  *
75  * Revision 1.2  1995/08/04  03:16:22  warmerda
76  * Added header.
77  *
78  */
79 
80 #include <stdlib.h>
81 #include <string.h>
82 #include "shapefil.h"
83 
84 SHP_CVSID("$Id: dbfdump.c,v 1.14 2016-12-05 12:44:05 erouault Exp $")
85 
main(int argc,char ** argv)86 int main( int argc, char ** argv )
87 
88 {
89     DBFHandle	hDBF;
90     int		*panWidth, i, iRecord;
91     char	szFormat[32], *pszFilename = NULL;
92     int		nWidth, nDecimals;
93     int		bHeader = 0;
94     int		bRaw = 0;
95     int		bMultiLine = 0;
96     char	szTitle[12];
97 
98 /* -------------------------------------------------------------------- */
99 /*      Handle arguments.                                               */
100 /* -------------------------------------------------------------------- */
101     for( i = 1; i < argc; i++ )
102     {
103         if( strcmp(argv[i],"-h") == 0 )
104             bHeader = 1;
105         else if( strcmp(argv[i],"-r") == 0 )
106             bRaw = 1;
107         else if( strcmp(argv[i],"-m") == 0 )
108             bMultiLine = 1;
109         else
110             pszFilename = argv[i];
111     }
112 
113 /* -------------------------------------------------------------------- */
114 /*      Display a usage message.                                        */
115 /* -------------------------------------------------------------------- */
116     if( pszFilename == NULL )
117     {
118 	printf( "dbfdump [-h] [-r] [-m] xbase_file\n" );
119         printf( "        -h: Write header info (field descriptions)\n" );
120         printf( "        -r: Write raw field info, numeric values not reformatted\n" );
121         printf( "        -m: Multiline, one line per field.\n" );
122 	exit( 1 );
123     }
124 
125 /* -------------------------------------------------------------------- */
126 /*      Open the file.                                                  */
127 /* -------------------------------------------------------------------- */
128     hDBF = DBFOpen( pszFilename, "rb" );
129     if( hDBF == NULL )
130     {
131 	printf( "DBFOpen(%s,\"r\") failed.\n", argv[1] );
132 	exit( 2 );
133     }
134 
135 /* -------------------------------------------------------------------- */
136 /*	If there is no data in this file let the user know.		*/
137 /* -------------------------------------------------------------------- */
138     if( DBFGetFieldCount(hDBF) == 0 )
139     {
140 	printf( "There are no fields in this table!\n" );
141 	exit( 3 );
142     }
143 
144 /* -------------------------------------------------------------------- */
145 /*	Dump header definitions.					*/
146 /* -------------------------------------------------------------------- */
147     if( bHeader )
148     {
149         for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
150         {
151             DBFFieldType	eType;
152             const char	 	*pszTypeName;
153             char chNativeType;
154 
155             chNativeType = DBFGetNativeFieldType( hDBF, i );
156 
157             eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
158             if( eType == FTString )
159                 pszTypeName = "String";
160             else if( eType == FTInteger )
161                 pszTypeName = "Integer";
162             else if( eType == FTDouble )
163                 pszTypeName = "Double";
164             else if( eType == FTInvalid )
165                 pszTypeName = "Invalid";
166 
167             printf( "Field %d: Type=%c/%s, Title=`%s', Width=%d, Decimals=%d\n",
168                     i, chNativeType, pszTypeName, szTitle, nWidth, nDecimals );
169         }
170     }
171 
172 /* -------------------------------------------------------------------- */
173 /*	Compute offsets to use when printing each of the field 		*/
174 /*	values. We make each field as wide as the field title+1, or 	*/
175 /*	the field value + 1. 						*/
176 /* -------------------------------------------------------------------- */
177     panWidth = (int *) malloc( DBFGetFieldCount( hDBF ) * sizeof(int) );
178 
179     for( i = 0; i < DBFGetFieldCount(hDBF) && !bMultiLine; i++ )
180     {
181 	DBFFieldType	eType;
182 
183 	eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
184 	if( (int) strlen(szTitle) > nWidth )
185 	    panWidth[i] = strlen(szTitle);
186 	else
187 	    panWidth[i] = nWidth;
188 
189 	if( eType == FTString )
190 	    sprintf( szFormat, "%%-%ds ", panWidth[i] );
191 	else
192 	    sprintf( szFormat, "%%%ds ", panWidth[i] );
193 	printf( szFormat, szTitle );
194     }
195     printf( "\n" );
196 
197 /* -------------------------------------------------------------------- */
198 /*	Read all the records 						*/
199 /* -------------------------------------------------------------------- */
200     for( iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ )
201     {
202         if( bMultiLine )
203             printf( "Record: %d\n", iRecord );
204 
205 	for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
206 	{
207             DBFFieldType	eType;
208 
209             eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
210 
211             if( bMultiLine )
212             {
213                 printf( "%s: ", szTitle );
214             }
215 
216 /* -------------------------------------------------------------------- */
217 /*      Print the record according to the type and formatting           */
218 /*      information implicit in the DBF field description.              */
219 /* -------------------------------------------------------------------- */
220             if( !bRaw )
221             {
222                 if( DBFIsAttributeNULL( hDBF, iRecord, i ) )
223                 {
224                     if( eType == FTString )
225                         sprintf( szFormat, "%%-%ds", nWidth );
226                     else
227                         sprintf( szFormat, "%%%ds", nWidth );
228 
229                     printf( szFormat, "(NULL)" );
230                 }
231                 else
232                 {
233                     switch( eType )
234                     {
235                       case FTString:
236                         sprintf( szFormat, "%%-%ds", nWidth );
237                         printf( szFormat,
238                                 DBFReadStringAttribute( hDBF, iRecord, i ) );
239                         break;
240 
241                       case FTInteger:
242                         sprintf( szFormat, "%%%dd", nWidth );
243                         printf( szFormat,
244                                 DBFReadIntegerAttribute( hDBF, iRecord, i ) );
245                         break;
246 
247                       case FTDouble:
248                         sprintf( szFormat, "%%%d.%dlf", nWidth, nDecimals );
249                         printf( szFormat,
250                                 DBFReadDoubleAttribute( hDBF, iRecord, i ) );
251                         break;
252 
253                       default:
254                         break;
255                     }
256                 }
257             }
258 
259 /* -------------------------------------------------------------------- */
260 /*      Just dump in raw form (as formatted in the file).               */
261 /* -------------------------------------------------------------------- */
262             else
263             {
264                 sprintf( szFormat, "%%-%ds", nWidth );
265                 printf( szFormat,
266                         DBFReadStringAttribute( hDBF, iRecord, i ) );
267             }
268 
269 /* -------------------------------------------------------------------- */
270 /*      Write out any extra spaces required to pad out the field        */
271 /*      width.                                                          */
272 /* -------------------------------------------------------------------- */
273 	    if( !bMultiLine )
274 	    {
275 		sprintf( szFormat, "%%%ds", panWidth[i] - nWidth + 1 );
276 		printf( szFormat, "" );
277 	    }
278 
279             if( bMultiLine )
280                 printf( "\n" );
281 
282 	    fflush( stdout );
283 	}
284 
285         if( DBFIsRecordDeleted(hDBF, iRecord) )
286             printf( "(DELETED)" );
287 
288 	printf( "\n" );
289     }
290 
291     DBFClose( hDBF );
292     free( panWidth );
293 
294     return( 0 );
295 }
296