{"id":37556292,"url":"https://github.com/WizardMac/ReadStat","last_synced_at":"2026-01-23T17:02:12.419Z","repository":{"id":4028209,"uuid":"5128518","full_name":"WizardMac/ReadStat","owner":"WizardMac","description":"Command-line tool (+ C library) for converting SAS, Stata, and SPSS files 💾","archived":false,"fork":false,"pushed_at":"2026-01-07T13:32:25.000Z","size":2303,"stargazers_count":301,"open_issues_count":48,"forks_count":78,"subscribers_count":18,"default_branch":"dev","last_synced_at":"2026-01-13T02:41:32.843Z","etag":null,"topics":["readstat","sas","sas7bdat","spss","stata"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WizardMac.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2012-07-20T21:17:40.000Z","updated_at":"2026-01-07T13:32:29.000Z","dependencies_parsed_at":"2023-02-15T23:31:09.335Z","dependency_job_id":"f590ea27-04dc-4de2-ab57-a154cf1a4b14","html_url":"https://github.com/WizardMac/ReadStat","commit_stats":{"total_commits":1046,"total_committers":24,"mean_commits":"43.583333333333336","dds":0.07265774378585088,"last_synced_commit":"4926250c8d7d8793153d7d8552a96f130eb68937"},"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/WizardMac/ReadStat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WizardMac%2FReadStat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WizardMac%2FReadStat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WizardMac%2FReadStat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WizardMac%2FReadStat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WizardMac","download_url":"https://codeload.github.com/WizardMac/ReadStat/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WizardMac%2FReadStat/sbom","scorecard":{"id":151833,"data":{"date":"2025-08-11","repo":{"name":"github.com/WizardMac/ReadStat","commit":"b2d5407d62caf3c33caadc0495c9f7684b6a0df7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":10,"reason":"16 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":2,"reason":"Found 8/30 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/codecov.yml:1","Warn: no topLevel permission defined: .github/workflows/fuzz.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:86: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/build.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codecov.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/codecov.yml/dev?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/fuzz.yml:8: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/fuzz.yml/dev?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/fuzz.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/fuzz.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/fuzz.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/WizardMac/ReadStat/fuzz.yml/dev?enable=pin","Warn: downloadThenRun not pinned by hash: .github/workflows/codecov.yml:26","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: OSSFuzz integration found","Info: CLibFuzzer integration found: src/fuzz/fuzz_compression_sas_rle.c:7","Info: CLibFuzzer integration found: src/fuzz/fuzz_compression_sav.c:7","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_dta.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_por.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_sas7bcat.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_sas7bdat.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_sas_commands.c:11","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_sav.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_spss_commands.c:11","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_stata_dictionary.c:11","Info: CLibFuzzer integration found: src/fuzz/fuzz_format_xport.c:10","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_dta_timestamp.c:7","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_por_double.c:6","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_sav_date.c:8","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_sav_time.c:8","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_spss_format.c:8","Info: CLibFuzzer integration found: src/fuzz/fuzz_grammar_xport_format.c:8"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.1.9 not signed: https://api.github.com/repos/WizardMac/ReadStat/releases/93071035","Warn: release artifact v1.1.8 not signed: https://api.github.com/repos/WizardMac/ReadStat/releases/66784743","Warn: release artifact v1.1.8-rc0 not signed: https://api.github.com/repos/WizardMac/ReadStat/releases/60062604","Warn: release artifact v1.1.7 not signed: https://api.github.com/repos/WizardMac/ReadStat/releases/48052813","Warn: release artifact v1.1.7-rc1 not signed: https://api.github.com/repos/WizardMac/ReadStat/releases/47310595","Warn: release artifact v1.1.9 does not have provenance: https://api.github.com/repos/WizardMac/ReadStat/releases/93071035","Warn: release artifact v1.1.8 does not have provenance: https://api.github.com/repos/WizardMac/ReadStat/releases/66784743","Warn: release artifact v1.1.8-rc0 does not have provenance: https://api.github.com/repos/WizardMac/ReadStat/releases/60062604","Warn: release artifact v1.1.7 does not have provenance: https://api.github.com/repos/WizardMac/ReadStat/releases/48052813","Warn: release artifact v1.1.7-rc1 does not have provenance: https://api.github.com/repos/WizardMac/ReadStat/releases/47310595"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: OSV-2021-732","Warn: Project is vulnerable to: OSV-2023-28","Warn: Project is vulnerable to: OSV-2024-1150"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'dev'","Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T10:54:47.380Z","repository_id":4028209,"created_at":"2025-08-16T10:54:47.380Z","updated_at":"2025-08-16T10:54:47.380Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28474301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T00:03:33.697Z","status":"ssl_error","status_checked_at":"2026-01-15T23:58:36.859Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["readstat","sas","sas7bdat","spss","stata"],"created_at":"2026-01-16T09:00:35.023Z","updated_at":"2026-01-23T17:02:12.413Z","avatar_url":"https://github.com/WizardMac.png","language":"C","funding_links":[],"categories":["Tools"],"sub_categories":["reading  and writing xpt file in C"],"readme":"[![GitHub CI build status](https://github.com/WizardMac/ReadStat/workflows/build/badge.svg)](https://github.com/WizardMac/ReadStat/actions)\n[![Appveyor build status](https://ci.appveyor.com/api/projects/status/76ctatpy3grlrd9x/branch/master?svg=true)](https://ci.appveyor.com/project/evanmiller/readstat/branch/master)\n[![codecov](https://codecov.io/gh/WizardMac/ReadStat/branch/master/graph/badge.svg)](https://codecov.io/gh/WizardMac/ReadStat)\n[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/readstat.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened\u0026can=1\u0026q=proj:readstat)\n\nReadStat: Read (and write) data sets from SAS, Stata, and SPSS\n==\n\nOriginally developed for [Wizard](https://www.wizardmac.com/), ReadStat is a\ncommand-line tool and MIT-licensed C library for reading files from popular\nstats packages. Supported data formats include:\n\n* SAS: SAS7BDAT (binary file) and XPORT (transport file)\n* Stata: DTA (binary file) versions 104-119\n* SPSS: POR (portable file), SAV (binary file), and ZSAV (compressed binary)\n\nSupported metadata formats include:\n\n* SAS: SAS7BCAT (catalog file) and .sas (command file)\n* Stata: .dct (dictionary file)\n* SPSS: .sps (command file)\n\nThere is also write support for all the data formats, but not the metadata\nformats. *The produced SAS7BDAT files still cannot be read by SAS*, but feel\nfree to contribute your binary-format expertise here.\n\nFor reading in R data files, please see the related\n[librdata](https://github.com/WizardMac/librdata) project.\n\nInstallation on Unix / macOS\n--\n\nGrab the latest [release](https://github.com/WizardMac/ReadStat/releases) and\nthen proceed as usual:\n\n    ./configure\n    make\n    sudo make install\n\nIf you're cloning the repository, first make sure you have autotools installed,\nand then run `./autogen.sh` to generate the configure file.\n\nIf you're on Mac and see errors about `AM_ICONV` when you run `./autogen.sh`,\nyou'll need to install [gettext](https://www.gnu.org/software/gettext/).\n\nInstallation on Windows\n--\n\nReadStat now includes a Microsoft Visual Studio project file that includes\nbuild targets for the library and tests. See the [VS17](./VS17) folder in\nthe downloaded release for a \"one-click\" Windows build.\n\nAlternatively, you can build ReadStat on the command line using an\n[msys2](https://msys2.github.io/) environment. After installing msys2,\ndownload some other packages:\n\n    pacman -S autoconf automake libtool make mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-libiconv\n\nThen start a MINGW command line (not the msys2 prompt!) and follow the UNIX\ninstall instructions above for this package.\n\nLanguage Bindings\n--\n\n* Julia: [ReadStat.jl](https://github.com/queryverse/ReadStat.jl)\n* Perl 6: [ReadStat.pm6](https://github.com/WizardMac/ReadStat.pm6)\n* Python: [pyreadstat](https://github.com/Roche/pyreadstat)\n* R: [haven](https://github.com/tidyverse/haven)\n* DuckDB: [`read_stat`](\u003chttps://github.com/mettekou/duckdb-read-stat\u003e)\n\n\nDocker\n--\n\nA dockerized version is available [here](https://github.com/jbn/readstat)\n\n\n\nCommand-line Usage\n--\n\nStandard usage:\n\n    readstat [-f] \u003cinput file\u003e \u003coutput file\u003e\n\nWhere:\n\n* `\u003cinput file\u003e` ends with `.dta`, `.por`, `.sav`, `.sas7bdat`, or `.xpt`and\n* `\u003coutput file\u003e` ends with `.dta`, `.por`, `.sav`, `.sas7bdat`, `.xpt` or `.csv`\n\nIf [libxlsxwriter](http://libxlsxwriter.github.io) is found at compile-time, an\nXLSX file (ending in `.xlsx`) can be written instead.\n\nIf zlib is found at compile-time, compressed SPSS files (`.zsav`) can be read\nand written as well.\n\nUse the `-f` option to overwrite an existing output file.\n\nIf you have a plain-text file described by a Stata dictionary file, a SAS\ncommand file, or an SPSS command file, a second invocation style is supported:\n\n    readstat \u003cinput file\u003e \u003cdictionary file\u003e \u003coutput file\u003e\n\nWhere:\n\n* `\u003cinput file\u003e` can be anything\n* `\u003cdictionary file\u003e` ends with `.dct`, `.sas`, or `.sps`\n* `\u003coutput file\u003e` ends with `.dta`, `.por`, `.sav`, `.xpt`, or `.csv`\n\nIf you have a SAS catalog file containing the data set's value labels, you\ncan use the same invocation:\n\n    readstat \u003cinput file\u003e \u003ccatalog file\u003e \u003coutput file\u003e\n\nExcept where:\n\n* `\u003cinput file\u003e` ends with `.sas7bdat`\n* `\u003ccatalog file\u003e` ends with `.sas7bcat`\n* `\u003coutput file\u003e` ends with `.dta`, `.por`, `.sav`, `.xpt`, or `.csv`\n\nIf the file conversion succeeds, ReadStat will report the number of rows and\nvariables converted, e.g.\n\n    Converted 111 variables and 160851 rows in 12.36 seconds\n\nAt the moment value labels are supported, but the finer nuances of converting\nformat strings (e.g. `%8.2g`) are not.\n\nCommand-line Usage with CSV input\n--\n\nA prerequisite for CSV input is that the [libcsv](https://github.com/rgamble/libcsv)\nlibrary is found at compile time.\n\nCSV input is supported together with a metadata file describing the data:\n\n    readstat \u003cinput file.csv\u003e \u003cinput metadata.json\u003e \u003coutput file\u003e\n\nThe `\u003coutput file\u003e` should end with `.dta`, `.sav`, or `.csv`.\n\nThe `\u003cinput file.csv\u003e` is a regular CSV file.\n\nThe `\u003cinput metadata.json\u003e` is a JSON file describing column types, value\nlabels and missing values. The easiest way to create such a metadata file is to\nuse the provided `extract_metadata` program on an existing file:\n\n    $ extract_metadata \u003cinput file.(dta|sav|sas7bcat)\u003e\n\nThe schema of this JSON file is fully described in\n[variablemetadata_schema.json](variablemetadata_schema.json) using [JSON\nSchema](http://json-schema.org/).\n\nThe following is an example of a valid metadata file:\n\n    {\n        \"type\": \"SPSS\",\n        \"variables\": [\n            {\n                \"type\": \"NUMERIC\",\n                \"name\": \"citizenship\",\n                \"label\": \"Citizenship of respondent\",\n                \"categories\": [\n                    {\n                        \"code\": 1,\n                        \"label\": \"Afghanistan\"\n                    },\n                    {\n                        \"code\": 2,\n                        \"label\": \"Albania\"\n                    },\n                    {\n                        \"code\": 98,\n                        \"label\": \"No answer\"\n                    },\n                    {\n                        \"code\": 99,\n                        \"label\": \"Not applicable\"\n                    }\n                ],\n                \"missing\": {\n                    \"type\": \"DISCRETE\",\n                    \"values\": [\n                        98,\n                        99\n                    ]\n                }\n            }\n        ]\n    }\n\nHere the column `citizenship` is a numeric column with four possible values `1`, `2`, `98`, and `99`.\n`1` has the label `Afghanistan`, `2` has `Albania`, `98` has `No answer` and `99` has `Not applicable`.\n`98` and `99` are defined as missing values.\n\nOther column types are `STRING` and `DATE`. \nAll values in `DATE` columns are expected to conform to [ISO 8601 date](https://en.wikipedia.org/wiki/ISO_8601).\nHere is an example of `DATE` metadata:\n\n    {\n        \"type\": \"SPSS\",\n        \"variables\": [\n            {\n                \"type\": \"DATE\",\n                \"name\": \"startdate\",\n                \"label\": \"Start date\",\n                \"categories\": [\n                    {\n                        \"code\": \"6666-01-01\",\n                        \"label\": \"no date available\"\n                    }\n                ],\n                \"missing\": {\n                    \"type\": \"DISCRETE\",\n                    \"values\": [\n                        \"6666-01-01\",\n                        \"9999-01-01\"\n                    ]\n                }\n            }\n        ]\n    }\n\nValue labels are supported for `DATE`.\n\nThe last column type is `STRING`:\n\n    {\n        \"type\": \"SPSS\",\n        \"variables\": [\n            {\n                \"type\": \"STRING\",\n                \"name\": \"somestring\",\n                \"label\": \"Label of column\",\n                \"missing\": {\n                    \"type\": \"DISCRETE\",\n                    \"values\": [\n                        \"NA\",\n                        \"N/A\"\n                    ]\n                }\n            }\n        ]\n    }\n\nValue labels are not supported for `STRING`.\n\nLibrary Usage: Reading Files\n--\n\nThe ReadStat API is callback-based. It uses very little memory, and is suitable\nfor programs with progress bars.  ReadStat uses\n[iconv](https://en.wikipedia.org/wiki/Iconv) to automatically transcode\ntext data into UTF-8, so you don't have to worry about character encodings. \n\nSee src/readstat.h for the complete API. In general you'll provide a filename\nand a set of optional callback functions for handling various information and\ndata found in the file. It's up to the user to store this information in an\nappropriate data structure. If a context pointer is passed to the parse_* functions,\nit will be made available to the various callback functions.\n\nCallback functions should return `READSTAT_HANDLER_OK` (zero) on success.\nReturning `READSTAT_HANDLER_ABORT` will abort the parsing process.\n\nExample: Return the number of records in a DTA file.\n\n```c\n#include \"readstat.h\"\n\nint handle_metadata(readstat_metadata_t *metadata, void *ctx) {\n    int *my_count = (int *)ctx;\n\n    *my_count = readstat_get_row_count(metadata);\n\n    return READSTAT_HANDLER_OK;\n}\n\nint main(int argc, char *argv[]) {\n    if (argc != 2) {\n        printf(\"Usage: %s \u003cfilename\u003e\\n\", argv[0]);\n        return 1;\n    }\n    int my_count = 0;\n    readstat_error_t error = READSTAT_OK;\n    readstat_parser_t *parser = readstat_parser_init();\n    readstat_set_metadata_handler(parser, \u0026handle_metadata);\n\n    error = readstat_parse_dta(parser, argv[1], \u0026my_count);\n\n    readstat_parser_free(parser);\n\n    if (error != READSTAT_OK) {\n        printf(\"Error processing %s: %d\\n\", argv[1], error);\n        return 1;\n    }\n    printf(\"Found %d records\\n\", my_count);\n    return 0;\n}\n```\n\nExample: Convert a DTA to a tab-separated file.\n\n```c\n#include \"readstat.h\"\n\nint handle_metadata(readstat_metadata_t *metadata, void *ctx) {\n    int *my_var_count = (int *)ctx;\n    \n    *my_var_count = readstat_get_var_count(metadata);\n\n    return READSTAT_HANDLER_OK;\n}\n\nint handle_variable(int index, readstat_variable_t *variable, \n    const char *val_labels, void *ctx) {\n    int *my_var_count = (int *)ctx;\n\n    printf(\"%s\", readstat_variable_get_name(variable));\n    if (index == *my_var_count - 1) {\n        printf(\"\\n\");\n    } else {\n        printf(\"\\t\");\n    }\n\n    return READSTAT_HANDLER_OK;\n}\n\nint handle_value(int obs_index, readstat_variable_t *variable, readstat_value_t value, void *ctx) {\n    int *my_var_count = (int *)ctx;\n    int var_index = readstat_variable_get_index(variable);\n    readstat_type_t type = readstat_value_type(value);\n    if (!readstat_value_is_system_missing(value)) {\n        if (type == READSTAT_TYPE_STRING) {\n            printf(\"%s\", readstat_string_value(value));\n        } else if (type == READSTAT_TYPE_INT8) {\n            printf(\"%hhd\", readstat_int8_value(value));\n        } else if (type == READSTAT_TYPE_INT16) {\n            printf(\"%hd\", readstat_int16_value(value));\n        } else if (type == READSTAT_TYPE_INT32) {\n            printf(\"%d\", readstat_int32_value(value));\n        } else if (type == READSTAT_TYPE_FLOAT) {\n            printf(\"%f\", readstat_float_value(value));\n        } else if (type == READSTAT_TYPE_DOUBLE) {\n            printf(\"%lf\", readstat_double_value(value));\n        }\n    }\n    if (var_index == *my_var_count - 1) {\n        printf(\"\\n\");\n    } else {\n        printf(\"\\t\");\n    }\n\n    return READSTAT_HANDLER_OK;\n}\n\nint main(int argc, char *argv[]) {\n    if (argc != 2) {\n        printf(\"Usage: %s \u003cfilename\u003e\\n\", argv[0]);\n        return 1;\n    }\n    int my_var_count = 0;\n    readstat_error_t error = READSTAT_OK;\n    readstat_parser_t *parser = readstat_parser_init();\n    readstat_set_metadata_handler(parser, \u0026handle_metadata);\n    readstat_set_variable_handler(parser, \u0026handle_variable);\n    readstat_set_value_handler(parser, \u0026handle_value);\n\n    error = readstat_parse_dta(parser, argv[1], \u0026my_var_count);\n\n    readstat_parser_free(parser);\n\n    if (error != READSTAT_OK) {\n        printf(\"Error processing %s: %d\\n\", argv[1], error);\n        return 1;\n    }\n    return 0;\n}\n```\n\nLibrary Usage: Writing Files\n--\n\nReadStat can write data sets to a number of file formats, and uses largely the\nsame API for each of them. Files are written incrementally, with the header\nwritten first, followed by individual rows of data, and ending with some kind\nof trailer. (So the full data file never resides in memory.) Unlike like the\ncallback-based API for reading files, the writer API consists of function that\nthe developer must call in a particular order. The complete API can be found in\n[readstat.h](./src/readstat.h).\n\nBasic usage:\n\n```c\n#include \"readstat.h\"\n\n/* A callback for writing bytes to your file descriptor of choice */\n/* The ctx argument comes from the readstat_begin_writing_xxx function */\nstatic ssize_t write_bytes(const void *data, size_t len, void *ctx) {\n    int fd = *(int *)ctx;\n    return write(fd, data, len);\n}\n\nint main(int argc, char *argv[]) {\n    readstat_writer_t *writer = readstat_writer_init();\n    readstat_set_data_writer(writer, \u0026write_bytes);\n    readstat_writer_set_file_label(writer, \"My data set\");\n\n    int row_count = 1;\n\n    readstat_variable_t *variable = readstat_add_variable(writer, \"Var1\", READSTAT_TYPE_DOUBLE, 0);\n    readstat_variable_set_label(variable, \"First variable\");\n\n    /* Call one of:\n     *   readstat_begin_writing_dta\n     *   readstat_begin_writing_por\n     *   readstat_begin_writing_sas7bdat\n     *   readstat_begin_writing_sav\n     *   readstat_begin_writing_xport\n     */\n\n    int fd = open(\"something.dta\", O_CREAT | O_WRONLY);\n    readstat_begin_writing_dta(writer, \u0026fd, row_count);\n\n    int i;\n    for (i=0; i\u003crow_count; i++) {\n        readstat_begin_row(writer);\n        readstat_insert_double_value(writer, variable, 1.0 * i);\n        readstat_end_row(writer);\n    }\n\n    readstat_end_writing(writer);\n    readstat_writer_free(writer);\n    close(fd);\n\n    return 0;\n}\n```\n\nFuzz Testing\n--\n\nTo assist in fuzz testing, ReadStat ships with target files designed to work\nwith [libFuzzer](http://llvm.org/docs/LibFuzzer.html). Clang 6 or later is\nrequired.\n\n1. `./configure --enable-fuzz-testing` turns on useful sanitizer and sanitizer-coverage flags\n1. `make` will create a new binary called `generate_corpus`. Running this\n   program will use the ReadStat test suite to create a corpus of test files in\n   `corpus/`. There is a subdirectory for each sub-format (`dta104`, `dta105`,\n   etc.). Currently a total of 468 files are created.\n1. If fuzz-testing has been enabled, `make` will also create fourteen fuzzer\n   targets, one for each of seven file formats, six for internally used\n   grammars, and two fuzzers for testing the compression routines.\n   * `fuzz_format_dta`\n   * `fuzz_format_por`\n   * `fuzz_format_sas7bcat`\n   * `fuzz_format_sas7bdat`\n   * `fuzz_format_sav`\n   * `fuzz_format_xport`\n   * `fuzz_format_stata_dictionary`\n   * `fuzz_grammar_dta_timestamp`\n   * `fuzz_grammar_por_double`\n   * `fuzz_grammar_sav_date`\n   * `fuzz_grammar_sav_time`\n   * `fuzz_grammar_spss_format`\n   * `fuzz_grammar_xport_format`\n   * `fuzz_compression_sas_rle`\n   * `fuzz_compression_sav`\n\nFor best results, each sub-directory of the corpus should be passed to the relevant fuzzer, e.g.:\n\n* `./fuzz_format_dta corpus/dta104`\n* `./fuzz_format_dta corpus/dta110`\n* ...\n* `./fuzz_format_sav corpus/sav`\n* `./fuzz_format_sav corpus/zsav`\n* `./fuzz_format_xport corpus/xpt5`\n* `./fuzz_format_xport corpus/xpt8`\n\nFinally, the compression fuzzers can be invoked without a corpus:\n\n* `./fuzz_compression_sas_rle`\n* `./fuzz_compression_sav`\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWizardMac%2FReadStat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FWizardMac%2FReadStat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWizardMac%2FReadStat/lists"}