{"id":45847,"date":"2026-11-10T03:53:18","date_gmt":"2026-11-10T03:53:18","guid":{"rendered":"https:\/\/www.withdata.com\/blog\/?p=45847"},"modified":"2026-11-12T14:48:45","modified_gmt":"2026-11-12T14:48:45","slug":"why-dbf-opens-empty-garbled-or-not-at-all","status":"publish","type":"post","link":"https:\/\/www.withdata.com\/blog\/dbtofile\/why-dbf-opens-empty-garbled-or-not-at-all.html","title":{"rendered":"Why Your .dbf Opens Empty, Garbled, or Not at All"},"content":{"rendered":"<p>A <code>.dbf<\/code> file looks like the simplest database in the world: fixed-width records, a header, no server. That is why it is so often the file that arrives by email with no explanation \u2014 payroll exports, a shipping list, a fifteen-year-old application&#8217;s table.<\/p>\n<p>It is also why it fails in ways that look like corruption but are not. Almost every &#8220;this .dbf is broken&#8221; case is one of three things: the table is missing a file it depends on, the text was written in a codepage nobody recorded, or the rows are there but deleted.<\/p>\n<h2>1. A <code>.dbf<\/code> is not always one file<\/h2>\n<p>A Visual FoxPro table is <code>customers.dbf<\/code> <strong>plus<\/strong> <code>customers.fpt<\/code>, which holds the memo (variable length text) blocks. Older dBase versions use <code>.dbt<\/code> for the same job. Only the <code>.dbf<\/code> holds the records and the field definitions; only the memo file holds the long text.<\/p>\n<p>Copy the <code>.dbf<\/code> alone, or receive just that one file, and there is nothing inside it that can reconstruct the memos. What happens next depends on the tool:<\/p>\n<ul>\n<li>some tools open the table and show the memo columns <strong>empty<\/strong> \u2014 quiet data loss, the worst outcome;<\/li>\n<li>others refuse the whole table.<\/li>\n<\/ul>\n<p>Here is the second behaviour, verbatim, from a table whose <code>.fpt<\/code> was left behind (Windows path abbreviated):<\/p>\n<pre><code>[error]  Unable to open file \"\u2026\\dbf_nofpt\\feed.FPT\": The system cannot find the file specified.<\/code><\/pre>\n<p>No rows, no warning about which column is affected \u2014 the table simply does not open. If you are about to send someone &#8220;the database&#8221;, send the <code>.fpt<\/code> (and the <code>.cdx<\/code> index if there is one) with it. If you already received one file, ask for the rest before assuming the data is gone.<\/p>\n<h2>2. The text is garbled because the codepage is not in the file<\/h2>\n<p>A <code>.dbf<\/code> stores text as bytes, one byte per character, and the file <em>may<\/em> declare which codepage those bytes belong to in a single header byte (the &#8220;language driver ID&#8221;). Old exports frequently carry <code>0x00<\/code> there \u2014 &#8220;no idea&#8221;.<\/p>\n<p>When the byte is missing, the reader falls back to the machine&#8217;s own ANSI codepage, which is whatever that PC was installed with. The same file therefore reads correctly on one machine and produces question marks on another, and neither user did anything wrong.<\/p>\n<p>The demonstration below is a two-file A\/B: identical content, identical bytes, one field differs \u2014 the codepage marker. Below, the same file read by <a href=\"https:\/\/www.withdata.com\/db-to-file\/\" target=\"_blank\" rel=\"noopener noreferrer\">DBToFile<\/a> with <code>Code Page<\/code> left on <code>Default<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.withdata.com\/wp\/wp-content\/uploads\/2026\/11\/dbfopen-02-default.png\" alt=\".dbf opened with the Code Page setting on Default: accented names arrive as Caf?? Z??rich, Fran?ois Fr?res\" width=\"968\"><\/p>\n<p><code>Caf\u00e9 Z\u00fcrich<\/code> \u2192 <code>Caf?? Z??rich<\/code>, <code>Fran\u00e7ois Fr\u00e8res<\/code> \u2192 <code>Fran?ois Fr?res<\/code>, <code>\u00d1and\u00fa S.A.<\/code> \u2192 <code>?and? S.A.<\/code>. Every non-ASCII character is replaced, silently, and the rest of the row looks perfectly sane.<\/p>\n<p>The same table, this time with the codepage declared in the file (or selected explicitly in the tool):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.withdata.com\/wp\/wp-content\/uploads\/2026\/11\/dbfopen-03-marked.png\" alt=\"The same table with the codepage known: Caf\u00e9 Z\u00fcrich, Fran\u00e7ois Fr\u00e8res, Besan\u00e7on, \u00d1and\u00fa S.A.\" width=\"968\"><\/p>\n<p>So the fix is not a repair tool, it is a setting. In <a href=\"https:\/\/www.withdata.com\/db-to-file\/\" target=\"_blank\" rel=\"noopener noreferrer\">DBToFile<\/a> it lives on the logon dialog, next to the folder \u2014 and it is a named list, not a number: <code>Default<\/code>, <code>UnitedStatesOEM<\/code>, <code>WesternEuropeanANSI<\/code>, <code>CentralEuropeanANSI<\/code>, <code>CyrillicANSI<\/code>, <code>GreekANSI<\/code>, <code>TurkishANSI<\/code>, <code>HebrewANSI<\/code>, <code>ArabicANSI<\/code>, <code>BalticANSI<\/code>, <code>Japanese<\/code>, <code>ChineseSimplified<\/code>, <code>ChineseTraditional<\/code>, <code>Korean<\/code>, and the matching DOS pages (24 entries in all).<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.withdata.com\/wp\/wp-content\/uploads\/2026\/11\/dbfopen-01-logon.png\" alt=\"DBToFile Logon: Database Type DBF, DBF Path (Folder), DBF Format VisualFoxPro, Code Page Default\" width=\"568\"><\/p>\n<p>Try <code>WesternEuropeanANSI<\/code> for accented Latin text, <code>CyrillicANSI<\/code> for Cyrillic, and leave <code>Default<\/code> when the file does declare its own codepage. The setting applies to the whole folder, which is correct: one folder is normally written by one application in one codepage.<\/p>\n<h2>3. The rows are there, but some of them are deleted<\/h2>\n<p>Visual FoxPro deletes a record by flipping a byte, not by removing it. The row stays in the file, fully readable, and is skipped only if the reader honours the flag.<\/p>\n<p>Measured on three real tables:<\/p>\n<table>\n<thead>\n<tr>\n<th>File<\/th>\n<th>Records in the header<\/th>\n<th>Marked deleted<\/th>\n<th>What a reader should show<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>feed.dbf<\/code><\/td>\n<td>64<\/td>\n<td>58<\/td>\n<td><strong>6<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>authors.dbf<\/code><\/td>\n<td>105<\/td>\n<td>5<\/td>\n<td><strong>100<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>bom.dbf<\/code><\/td>\n<td>118,043<\/td>\n<td>95,681<\/td>\n<td><strong>22,362<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The middle column is not a defect \u2014 it is how the format works, and a tool that ignores the flag reports 64 rows where the application has always shown 6. Row counts are the first thing anyone checks, so get them from a reader that honours the flag (or compare with the count the application itself displays).<\/p>\n<h2>4. Reading it: three steps, no driver<\/h2>\n<p>Nothing above needs FoxPro, a dBase install, or an ODBC driver. The Access\/DBF engines that other tools insist on are an OLE DB layer; a reader that understands the file format can parse the pages directly and never asks Windows for a provider. Access files are the same story with a different container \u2014 <a href=\"https:\/\/www.withdata.com\/blog\/dbtofile\/open-mdb-accdb-without-ace-provider.html\" target=\"_blank\" rel=\"noopener noreferrer\">opening an .mdb or .accdb without the ACE provider<\/a>.<\/p>\n<ol>\n<li>Start <a href=\"https:\/\/www.withdata.com\/db-to-file\/\" target=\"_blank\" rel=\"noopener noreferrer\">DBToFile<\/a>. The first window is <code>DBToFile Logon<\/code>.<\/li>\n<li><code>Database Type<\/code> = <code>DBF<\/code>, then give the <strong>folder<\/strong> in <code>DBF Path (Folder)<\/code> \u2014 a folder, not a file.<\/li>\n<\/ol>\n<p><code>DBF Format<\/code> = <code>Auto<\/code> lets the reader decide the dialect from the version byte; set <code>VisualFoxPro<\/code> explicitly if <code>Auto<\/code> ever guesses wrong. <code>Code Page<\/code> as described in \u00a72.<\/p>\n<ol>\n<li>Press <code>Connect<\/code>. The left pane lists every table in the folder. Double-click one and the grid<\/li>\n<\/ol>\n<p>fills; the status line reports the count and the time, e.g. <code>6 record(s), 0.031 second(s)<\/code>.<\/p>\n<p>Memo columns show a placeholder in the grid (<code>(WIDEMEMO)<\/code>) because they can hold megabytes; a double-click opens the value on its own:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.withdata.com\/wp\/wp-content\/uploads\/2026\/11\/dbfopen-04-memo.png\" alt=\"Memo column CHILDREN opened in its own window: Rezolution Pictures International\" width=\"704\"><\/p>\n<p>That is the whole check: the count matches what the application shows, the memo text is there, the accented characters are right. If all three pass, the file is fine and anything else is a conversion question.<\/p>\n<h3>If you need a file instead of a grid<\/h3>\n<p>Once the count and the text look right, the same window exports the table \u2014 <strong>CSV, Excel (<code>.xlsx<\/code>), <code>SQL<\/code>, <code>TXT<\/code>, <code>TSV<\/code>, <code>XML<\/code>, <code>JSON<\/code>, <code>Html<\/code>, <code>Fixed<\/code> or <code>Yaml<\/code><\/strong>:<\/p>\n<p><code>Start a task - DBToFile<\/code> \u2192 <code>Export From Table<\/code> \u2192 pick the table \u2192 <code>Set Target<\/code> chooses the format and the output file \u2192 <code>Convert Data<\/code> writes it. A clean <code>.dbf<\/code> \u2192 <code>.csv<\/code> or <code>.dbf<\/code> \u2192 <code>.xlsx<\/code> job is two clicks past the point where the grid already showed you the data was fine.<\/p>\n<h3>From the command line<\/h3>\n<pre><code>DBToFile.exe export --from=\"DBF:E:\/data\/dbf\" --table=feed --to=csv --out=feed.csv<\/code><\/pre>\n<p>Add <code>--set=SourceDB.CodePage=dpWesternEuropeanANSI<\/code> when the file does not declare its codepage \u2014 the same setting as the dialog, spelled for the session file.<\/p>\n<p><!-- wd-cta:dbf2excel --><\/p>\n<p><strong>Need the .dbf in Excel?<\/strong> <a href=\"https:\/\/www.withdata.com\/tools\/db-to-file\/dbf-to-excel\">Convert DBF to Excel (.xlsx)<\/a> keeps the DBF field types, decodes the code page and pulls the memo (DBT\/FPT) fields in as text, instead of a half-empty sheet (free trial, Windows\/macOS\/Linux).<\/p>\n<h2>FAQ<\/h2>\n<h3>Is one .dbf file the whole table?<\/h3>\n<p>Only if the table has no memo and no index. A Visual FoxPro table is <code>.dbf<\/code> + <code>.fpt<\/code> (memo) + <code>.cdx<\/code> (index); older dBase uses <code>.dbt<\/code> for the memo. Without the memo file the long text is not recoverable from the <code>.dbf<\/code> alone.<\/p>\n<h3>Why do I get question marks instead of accented letters?<\/h3>\n<p>The bytes are one-byte characters, and the reader has to be told which codepage they belong to. If the file does not declare it, the machine&#8217;s ANSI codepage is used, which is often not the one the file was written in. Set the codepage on the logon dialog and the same file reads correctly.<\/p>\n<h3>Do I need FoxPro, dBase or an ODBC driver installed?<\/h3>\n<p>No, for reading. A reader that parses the format itself does not go through OLE DB, so the &#8220;Provider cannot be found&#8221; class of error does not apply. If your own program opens the file through ODBC, then yes, and the driver&#8217;s bit-ness has to match your program.<\/p>\n<h3>Why does the row count differ from the file&#8217;s record count?<\/h3>\n<p>Deleted records stay in the file with a flag set. A 64-record file can legitimately show 6 rows. Count what the application shows, not what the header says.<\/p>\n<h3>Can it read a .dbf written by a Chinese\/Greek\/Cyrillic application?<\/h3>\n<p>Yes, when the codepage is selected or declared \u2014 that is exactly what the <code>Code Page<\/code> list is for. The risk is only that non-ASCII characters are replaced when the codepage is unknown.<\/p>\n<h3>Can I do this on a schedule?<\/h3>\n<p>Yes. Save the task once in the GUI, then run the same session from the command line or the scheduler.<\/p>\n<h2>Trying it on your own .dbf<\/h2>\n<blockquote>\n<p><strong>Open a <code>.dbf<\/code> that has no FoxPro and no driver behind it, and see the memo and the text before you export anything.<\/strong> <a href=\"https:\/\/www.withdata.com\/db-to-file\/\" target=\"_blank\" rel=\"noopener noreferrer\">Try DBToFile<\/a> \u2014 open the folder, check the memo and the non-ASCII text in the grid, then export to CSV, Excel or JSON. Windows \/ macOS \/ Linux, one-time price. To move the same table into SQL Server, MySQL or PostgreSQL instead of a file, that is <a href=\"https:\/\/www.withdata.com\/db-copier\/\" target=\"_blank\" rel=\"noopener noreferrer\">DBCopier<\/a>&#8216;s job \u2014 the type, id and memo details of that move are in the <a href=\"https:\/\/www.withdata.com\/blog\/dbcopier\/visual-foxpro-migration-dbf-cdx-fpt-to-sql-server.html\" target=\"_blank\" rel=\"noopener noreferrer\">Visual FoxPro migration walkthrough<\/a>.<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>A .dbf file looks like the simplest database in the world: fixed-width records, a header, no server. That is why it is so often the file that arrives by email with no explanation \u2014 payroll exports, a shipping list, a fifteen-year-old application&#8217;s table. It is also why it fails in ways that look like corruption [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2773],"tags":[13862,13860,13861,5569,13131,13772],"class_list":["post-45847","post","type-post","status-publish","format-standard","hentry","category-dbtofile","tag-dbf-codepage","tag-dbf-file","tag-dbf-memo","tag-dbf-to-csv","tag-dbf-to-excel","tag-dbtofile"],"_links":{"self":[{"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/posts\/45847","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/comments?post=45847"}],"version-history":[{"count":4,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/posts\/45847\/revisions"}],"predecessor-version":[{"id":45942,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/posts\/45847\/revisions\/45942"}],"wp:attachment":[{"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/media?parent=45847"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/categories?post=45847"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.withdata.com\/blog\/wp-json\/wp\/v2\/tags?post=45847"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}