# Introduction to Rparadox

## Introduction

Rparadox provides a simple and efficient way to read data from Paradox database files (`.db`) directly into R as modern `tibble` data frames. It uses the underlying `pxlib` C library to handle the low-level file format details and provides a clean, user-friendly R interface.

This package is designed to “just work” for the most common use case: extracting the full dataset from a Paradox table, including its associated BLOB/memo file (`.mb`).

### Features

- Direct Reading: Reads Paradox `.db` files without needing database drivers or external software.
- Tibble Output: Returns data in the `tibble` format, fully compatible with the Tidyverse ecosystem.
- Automatic BLOB Handling: Automatically detects, attaches, and reads data from associated memo/BLOB (`.mb`) files.
- Encryption Support: Supports reading password-protected Paradox files.
- Character Encoding Control: Automatically handles character encoding conversion to UTF-8 and allows manual override of the source encoding for files with incorrect headers.
- Type Conversion: Correctly maps Paradox data types to their corresponding R types, including `Date`, `Time` (`hms`), `Timestamp` (`POSIXct`), `Logical`, `Integer`, `Numeric`, and binary `blob` objects.

## Installation

    # stable version from CRAN
    install.packages("Rparadox")

You can install the development version from GitHub:

    # install.packages("devtools")
    devtools::install_github("celebithil/Rparadox")

## Basic Usage: `read_paradox()`

The easiest way to read a Paradox file is with the high-level `read_paradox()` function. It handles opening the file, reading the data, and closing the connection in a single step.

    # Get the path to an example database included with the package
    db_path <- system.file("extdata", "biolife.db", package = "Rparadox")

    # Read the data directly into a tibble
    # This automatically finds 'biolife.mb' and handles data types.
    biolife_data <- read_paradox(db_path)

    # View the data
    print(biolife_data)
    #> # A tibble: 28 × 8
    #>    `Species No` Category      Common_Name `Species Name` `Length (cm)` Length_In
    #>           <dbl> <chr>         <chr>       <chr>                  <dbl>     <dbl>
    #>  1        90020 Triggerfish   Clown Trig… Ballistoides …            50     19.7
    #>  2        90030 Snapper       Red Emperor Lutjanus sebae            60     23.6
    #>  3        90050 Wrasse        Giant Maor… Cheilinus und…           229     90.2
    #>  4        90070 Angelfish     Blue Angel… Pomacanthus n…            30     11.8
    #>  5        90080 Cod           Lunartail … Variola louti             80     31.5
    #>  6        90090 Scorpionfish  Firefish    Pterois volit…            38     15.0
    #>  7        90100 Butterflyfish Ornate But… Chaetodon Orn…            19      7.48
    #>  8        90110 Shark         Swell Shark Cephaloscylli…           102     40.2
    #>  9        90120 Ray           Bat Ray     Myliobatis ca…            56     22.0
    #> 10        90130 Eel           California… Gymnothorax m…           150     59.1
    #> # ℹ 18 more rows
    #> # ℹ 2 more variables: Notes <chr>, Graphic <blob>

    # Plot raw image data
    library(magick)
    #> Linking to ImageMagick 7.1.2.26
    #> Enabled features: cairo, fontconfig, freetype, fftw, heic, lcms, raw, rsvg, webp, x11
    #> Disabled features: ghostscript, pango
    #> Using 7 threads

    as.raw(biolife_data$Graphic[[1]]) |> image_read() |> plot()

## Reading Encrypted Files

If your Paradox file is password-protected, provide the password using the `password` argument:

    library(Rparadox)
    # Read a password-protected file
    secure_data <- read_paradox("path/to/encrypted.db", password = "secret_password")

If the file is encrypted and no password (or an incorrect one) is provided, the function will stop with an error message.

## Handling Character Encodings

For legacy files with incorrect encoding information in the header, you can specify the correct encoding manually with the `encoding` parameter:

    library(Rparadox)
    # This tells the package to interpret the source data as CP866
    data <- read_paradox("path/to/your/file.db", encoding = "cp866")

This ensures that all text fields are correctly converted to UTF-8 in the final `tibble`.

## Advanced Usage: Metadata and Manual Control

If you need more control — for instance, to inspect metadata before committing to reading a large dataset — you can use the lower-level functions.

The workflow is:

1. `pxlib_open_file()` to get a file handle.
2. `pxlib_metadata()` to inspect metadata (optional).
3. `pxlib_get_data()` to read the data.
4. `pxlib_close_file()` to release the connection.

    db_path <- system.file("extdata", "biolife.db", package = "Rparadox")

    # Open the file and get a handle
    pxdoc <- pxlib_open_file(db_path)

    if (!is.null(pxdoc)) {
      # Get metadata without reading all the data
      metadata <- pxlib_metadata(pxdoc)

      # Metadata includes human-readable field types and detected encoding
      cat("Encoding:", metadata$encoding, "\n")
      cat("Number of records:", metadata$num_records, "\n")
      print(head(metadata$fields))

      # Read the actual data
      data_table <- pxlib_get_data(pxdoc)

      # Always close the file when you're done
      pxlib_close_file(pxdoc)

      print(data_table)
    }
    #> Encoding: CP437
    #> Number of records: 28
    #>           name   type size
    #> 1   Species No Number    8
    #> 2     Category  Alpha   15
    #> 3  Common_Name  Alpha   30
    #> 4 Species Name  Alpha   40
    #> 5  Length (cm) Number    8
    #> 6    Length_In Number    8
    #> # A tibble: 28 × 8
    #>    `Species No` Category      Common_Name `Species Name` `Length (cm)` Length_In
    #>           <dbl> <chr>         <chr>       <chr>                  <dbl>     <dbl>
    #>  1        90020 Triggerfish   Clown Trig… Ballistoides …            50     19.7
    #>  2        90030 Snapper       Red Emperor Lutjanus sebae            60     23.6
    #>  3        90050 Wrasse        Giant Maor… Cheilinus und…           229     90.2
    #>  4        90070 Angelfish     Blue Angel… Pomacanthus n…            30     11.8
    #>  5        90080 Cod           Lunartail … Variola louti             80     31.5
    #>  6        90090 Scorpionfish  Firefish    Pterois volit…            38     15.0
    #>  7        90100 Butterflyfish Ornate But… Chaetodon Orn…            19      7.48
    #>  8        90110 Shark         Swell Shark Cephaloscylli…           102     40.2
    #>  9        90120 Ray           Bat Ray     Myliobatis ca…            56     22.0
    #> 10        90130 Eel           California… Gymnothorax m…           150     59.1
    #> # ℹ 18 more rows
    #> # ℹ 2 more variables: Notes <chr>, Graphic <blob>

## Links

- pxlib C library: https://github.com/steinm/pxlib
- CRAN page: https://cran.r-project.org/package=Rparadox
- Bug reports: https://github.com/celebithil/Rparadox/issues