DeepSeek辅助编写的dmp转schema和csv文件c语言程序

利用直接读dmp文件,字符串匹配和配对括号来提取DDL语句,不依赖odv_api函数。导出csv仍然依靠odv_api函数。

c 复制代码
#include "odv_api.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h> 
#include <getopt.h> 
#ifdef _WIN32
    #include <direct.h>
    #define MKDIR(dir) _mkdir(dir)
#else
    #include <sys/stat.h>
    #define MKDIR(dir) mkdir(dir, 0755)
#endif

/*---------------------------------------------------------------------------
    Global variables
 ---------------------------------------------------------------------------*/
static const char *g_output_dir = ".";
static char **g_table_list = NULL;
static int g_table_count = 0;
static char g_delimiter = ',';
static int g_write_header = 1;
static int g_write_types = 0;
static int g_export_all = 1;

/*---------------------------------------------------------------------------
    Table list structure for collecting table info
 ---------------------------------------------------------------------------*/
#define MAX_TABLES 200
typedef struct {
    int count;
    char names[MAX_TABLES][256];
    char schemas[MAX_TABLES][256];
    long long row_counts[MAX_TABLES];
} TableList;

static TableList g_tables;
static int g_export_success_count = 0;
static int g_export_fail_count = 0;

/*---------------------------------------------------------------------------
    print_usage
 ---------------------------------------------------------------------------*/
static void print_usage(const char *program_name)
{
    printf("Usage: %s <dump_file> [options]\n\n", program_name);
    printf("Options:\n");
    printf("  -o <dir>        Output directory (default: current directory)\n");
    printf("  -t </td>      Export specific table (can be used multiple times)\n");
    printf("  -a              Export all tables (default)\n");
    printf("  -d <delimiter>  CSV delimiter character (default: ',')\n");
    printf("  -H              Write header row (default: enabled)\n");
    printf("  -T              Write column types row after header\n");
    printf("  -h              Show this help message\n\n");
    printf("Examples:\n");
    printf("  %s export.dmp -o ./output -a\n", program_name);
    printf("  %s export.dmp -t TABLE1 -t TABLE2 -o ./csv_files\n", program_name);
    printf("  %s export.dmp -t EMPLOYEES -d '|' -H\n", program_name);
}

/*---------------------------------------------------------------------------
    create_directory
 ---------------------------------------------------------------------------*/
static int create_directory(const char *path)
{
    if (MKDIR(path) == 0) {
        return 1;
    }
    return 1; /* Assume directory exists */
}

/*---------------------------------------------------------------------------
    sanitize_filename - replace invalid characters with underscore
 ---------------------------------------------------------------------------*/
static void sanitize_filename(const char *input, char *output, int output_size)
{
    int i, j = 0;
    
    for (i = 0; input[i] && j < output_size - 1; i++) {
        char c = input[i];
        if (c == '/' || c == '\\' || c == ':' || c == '*' || 
            c == '?' || c == '"' || c == '<' || c == '>' || c == '|') {
            output[j++] = '_';
        } else {
            output[j++] = c;
        }
    }
    output[j] = '\0';
}

/*---------------------------------------------------------------------------
    build_output_path
 ---------------------------------------------------------------------------*/
static char* build_output_path(const char *output_dir, const char *table_name)
{
    char *full_path = NULL;
    char safe_table_name[256];
    int len;
    
    sanitize_filename(table_name, safe_table_name, sizeof(safe_table_name));
    
    len = strlen(output_dir) + strlen(safe_table_name) + 10;
    full_path = (char*)malloc(len);
    if (full_path) {
        sprintf(full_path, "%s/%s.csv", output_dir, safe_table_name);
    }
    
    return full_path;
}

/*---------------------------------------------------------------------------
    table_callback - called for each table when listing tables
 ---------------------------------------------------------------------------*/
static void __stdcall table_callback(
    const char *schema,
    const char *table,
    int col_count,
    const char **col_names,
    const char **col_types,
    const int *col_not_nulls,
    const char **col_defaults,
    int constraint_count,
    const char *constraints_json,
    long row_count,
    long data_offset,
    void *user_data)
{
    TableList *tl = (TableList *)user_data;
    
    if (tl->count < MAX_TABLES) {
        strncpy(tl->schemas[tl->count], schema ? schema : "", 255);
        strncpy(tl->names[tl->count], table ? table : "", 255);
        tl->schemas[tl->count][255] = '\0';
        tl->names[tl->count][255] = '\0';
        tl->row_counts[tl->count] = row_count;
        tl->count++;
        
        printf("  Found table: %s (schema: %s, columns: %d, rows: %lld)\n",
               table, schema, col_count, (long long)row_count);
    }
}

/*---------------------------------------------------------------------------
    instr - find substring in binary data (handles embedded \0)
    haystack: pointer to binary data
    haystack_len: length of haystack in bytes
    needle: search string (null-terminated)
    Returns: pointer to first occurrence, or NULL if not found
 ---------------------------------------------------------------------------*/
static char* instr(const char *haystack, size_t haystack_len, const char *needle)
{
    size_t needle_len = strlen(needle);
    
    if (needle_len == 0 || haystack_len < needle_len) {
        return NULL;
    }
    
    for (size_t i = 0; i <= haystack_len - needle_len; i++) {
        size_t j;
        for (j = 0; j < needle_len; j++) {
            if (haystack[i + j] != needle[j]) {
                break;
            }
        }
        if (j == needle_len) {
            return (char*)&haystack[i];
        }
    }
    
    return NULL;
}
/*---------------------------------------------------------------------------
    export_schema_for_table - export CREATE TABLE DDL for a specific table
    Directly read DMP file and extract CREATE TABLE statement by string matching
 ---------------------------------------------------------------------------*/
static int export_schema_for_table(const char *dump_file, const char *table_name, 
                                    const char *output_dir)
{
    FILE *dmp_fp = NULL;
    FILE *schema_file = NULL;
    char schema_path[512];
    char *file_content = NULL;
    long file_size;
    int rc = -1;
    
    /* Build schema file path */
    snprintf(schema_path, sizeof(schema_path), "%s/schema.sql", output_dir);
    
    /* Open dump file */
    dmp_fp = fopen(dump_file, "rb");
    if (!dmp_fp) {
        return -1;
    }
    
    /* Get file size */
    fseek(dmp_fp, 0, SEEK_END);
    file_size = ftell(dmp_fp);
    fseek(dmp_fp, 0, SEEK_SET);
    
    /* Read entire file */
    file_content = (char*)malloc(file_size + 1);
    if (!file_content) {
        fclose(dmp_fp);
        return -1;
    }
    fread(file_content, 1, file_size, dmp_fp);
    file_content[file_size] = '\0';
    fclose(dmp_fp);
    
    /* Open schema file for append */
    schema_file = fopen(schema_path, "a");
    if (!schema_file) {
        free(file_content);
        return -1;
    }
    
    /* Build search pattern: CREATE TABLE "TABLE_NAME" */
    char search_pattern[512];
    snprintf(search_pattern, sizeof(search_pattern), "CREATE TABLE \"%s\"", table_name);
    
    /* Search for pattern in binary data */
    char *found = instr(file_content, file_size, search_pattern);
    
    if (found) {
        char *start = found;
        char *paren_start = NULL;
        char *end = NULL;
        int paren_count = 0;
        
        /* Find the first '(' after CREATE TABLE */
        for (char *p = start; p < file_content + file_size; p++) {
            if (*p == '(') {
                paren_start = p;
                break;
            }
        }
        
        if (paren_start) {
            /* Find matching closing parenthesis */
            end = paren_start;
            while (end < file_content + file_size) {
                if (*end == '(') {
                    paren_count++;
                } else if (*end == ')') {
                    paren_count--;
                    if (paren_count == 0) {
                        end++;
                        break;
                    }
                }
                end++;
            }
        }
        
        if (end && end > start) {
            int ddl_len = end - start;
            char *ddl = (char*)malloc(ddl_len + 1);
            if (ddl) {
                strncpy(ddl, start, ddl_len);
                ddl[ddl_len] = '\0';
                
                /* Write to schema file */
                fprintf(schema_file, "\n-- Table: %s\n", table_name);
                fputs(ddl, schema_file);
                fprintf(schema_file, ";\n");
                
                free(ddl);
                rc = 0;
            }
        }
    }
    
    if (rc != 0) {
        fprintf(schema_file, "\n-- Table: %s (CREATE TABLE statement not found)\n", table_name);
    }
    
    fclose(schema_file);
    free(file_content);
    
    return rc;
}
/*---------------------------------------------------------------------------
    export_single_table - export one table to CSV
 ---------------------------------------------------------------------------*/
static int export_single_table(ODV_SESSION *session, const char *dump_file,
                                const char *table_name, const char *output_path, 
                                const char *output_dir)
{
    int rc;
    
    /* Export schema (CREATE TABLE) first */
    export_schema_for_table(dump_file, table_name, output_dir);
    
    /* Set CSV options */
    odv_set_csv_options(session, g_write_header, g_write_types);
    odv_set_csv_delimiter(session, g_delimiter);
    
    /* Export to CSV */
    rc = odv_export_csv(session, table_name, output_path);
    
    return rc;
}

/*---------------------------------------------------------------------------
    export_all_tables - export all tables from dump file
 ---------------------------------------------------------------------------*/
static int export_all_tables(const char *dump_file, const char *output_dir)
{
    ODV_SESSION *session = NULL;
    TableList tables;
    int rc;
    int i;
    int exported = 0;
    int dump_type;
    
    printf("Phase 1: Listing tables in %s\n", dump_file);
    printf("----------------------------------------\n");
    
    /* Initialize table list */
    memset(&tables, 0, sizeof(tables));
    
    /* Create session and list tables */
    rc = odv_create_session(&session);
    if (rc != ODV_OK || !session) {
        printf("ERROR: Failed to create session\n");
        return -1;
    }
    
    rc = odv_set_dump_file(session, dump_file);
    if (rc != ODV_OK) {
        printf("ERROR: Failed to set dump file: %s\n", odv_get_last_error(session));
        odv_destroy_session(session);
        return -1;
    }
    
    odv_check_dump_kind(session, &dump_type);
    odv_set_table_callback(session, table_callback, &tables);
    odv_list_tables(session);
    
    printf("\nFound %d tables\n\n", tables.count);
    
    if (tables.count == 0) {
        printf("No tables found in dump file.\n");
        odv_destroy_session(session);
        return 0;
    }
    
    /* Create output directory */
    create_directory(output_dir);
    
    printf("Phase 2: Exporting tables to CSV\n");
    printf("----------------------------------------\n");
    /* Initialize schema.sql file */
    char schema_path[512];
    snprintf(schema_path, sizeof(schema_path), "%s/schema.sql", output_dir);
    FILE *schema_file = fopen(schema_path, "w");
    if (schema_file) {
        fprintf(schema_file, "-- Oracle DMP Schema Export\n");
        fprintf(schema_file, "-- Generated by OraDB Dump Viewer\n");
        fprintf(schema_file, "-- Export time: %s\n\n", __DATE__ " " __TIME__);
        fclose(schema_file);
    }    
    /* Export each table - create new session for each export */
    for (i = 0; i < tables.count; i++) {
        char *output_path = build_output_path(output_dir, tables.names[i]);
        ODV_SESSION *export_session = NULL;
        
        if (!output_path) {
            printf("  [%d/%d] Table: %s -> SKIP (memory allocation failed)\n",
                   i + 1, tables.count, tables.names[i]);
            g_export_fail_count++;
            continue;
        }
        
        printf("  [%d/%d] Exporting table: %s -> %s\n",
               i + 1, tables.count, tables.names[i], output_path);
        
        /* Create new session for each export to avoid state issues */
        rc = odv_create_session(&export_session);
        if (rc != ODV_OK || !export_session) {
            printf("    ERROR: Failed to create session\n");
            free(output_path);
            g_export_fail_count++;
            continue;
        }
        
        rc = odv_set_dump_file(export_session, dump_file);
        if (rc != ODV_OK) {
            printf("    ERROR: Failed to set dump file: %s\n", 
                   odv_get_last_error(export_session));
            odv_destroy_session(export_session);
            free(output_path);
            g_export_fail_count++;
            continue;
        }
        
        /* Export to CSV */
        rc = export_single_table(export_session, dump_file, tables.names[i], output_path, output_dir);
        
        if (rc == ODV_OK) {
            long file_size;
            FILE *f = fopen(output_path, "rb");
            if (f) {
                fseek(f, 0, SEEK_END);
                file_size = ftell(f);
                fclose(f);
            } else {
                file_size = 0;
            }
            printf("    SUCCESS: %ld bytes, %lld rows\n", 
                   file_size, (long long)tables.row_counts[i]);
            exported++;
            g_export_success_count++;
        } else {
            printf("    FAILED: %s\n", odv_get_last_error(export_session));
            g_export_fail_count++;
        }
        
        odv_destroy_session(export_session);
        free(output_path);
    }
    
    odv_destroy_session(session);
    
    printf("\nExport completed: %d/%d tables exported successfully.\n", 
           exported, tables.count);
    
    return 0;
}

/*---------------------------------------------------------------------------
    export_selected_tables - export only specified tables
 ---------------------------------------------------------------------------*/
static int export_selected_tables(const char *dump_file, const char *output_dir,
                                   char **table_list, int table_count)
{
    ODV_SESSION *session = NULL;
    int rc;
    int i;
    int exported = 0;
    int dump_type;
    
    printf("Exporting %d specified tables...\n\n", table_count);
    
    /* Create output directory */
    create_directory(output_dir);
    /* Initialize schema.sql file */
    char schema_path[512];
    snprintf(schema_path, sizeof(schema_path), "%s/schema.sql", output_dir);
    FILE *schema_file = fopen(schema_path, "w");
    if (schema_file) {
        fprintf(schema_file, "-- Oracle DMP Schema Export\n");
        fprintf(schema_file, "-- Generated by OraDB Dump Viewer\n");
        fprintf(schema_file, "-- Export time: %s\n\n", __DATE__ " " __TIME__);
        fclose(schema_file);
    }    
    /* Export each table - create new session for each export to avoid state issues */
    for (i = 0; i < table_count; i++) {
        char *output_path = build_output_path(output_dir, table_list[i]);
        
        if (!output_path) {
            printf("  [%d/%d] Table: %s -> SKIP (memory allocation failed)\n",
                   i + 1, table_count, table_list[i]);
            g_export_fail_count++;
            continue;
        }
        
        printf("  [%d/%d] Exporting table: %s -> %s\n",
               i + 1, table_count, table_list[i], output_path);
        
        /* Create new session for each export */
        rc = odv_create_session(&session);
        if (rc != ODV_OK || !session) {
            printf("    ERROR: Failed to create session\n");
            free(output_path);
            g_export_fail_count++;
            continue;
        }
        
        rc = odv_set_dump_file(session, dump_file);
        if (rc != ODV_OK) {
            printf("    ERROR: Failed to set dump file: %s\n", 
                   odv_get_last_error(session));
            odv_destroy_session(session);
            free(output_path);
            g_export_fail_count++;
            continue;
        }
        
        /* Export to CSV */
        rc = export_single_table(session, dump_file, table_list[i], output_path, output_dir);
        
        if (rc == ODV_OK) {
            long file_size;
            FILE *f = fopen(output_path, "rb");
            if (f) {
                fseek(f, 0, SEEK_END);
                file_size = ftell(f);
                fclose(f);
            } else {
                file_size = 0;
            }
            printf("    SUCCESS: %ld bytes\n", file_size);
            exported++;
            g_export_success_count++;
        } else {
            printf("    FAILED: %s\n", odv_get_last_error(session));
            g_export_fail_count++;
        }
        
        odv_destroy_session(session);
        session = NULL;
        free(output_path);
    }
    
    printf("\nExport completed: %d/%d tables exported successfully.\n", 
           exported, table_count);
    
    return 0;
}

/*---------------------------------------------------------------------------
    main
 ---------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    const char *dump_file = NULL;
    int opt;
    
    /* Parse command line arguments */
    while ((opt = getopt(argc, argv, "o:t:d:HTah")) != -1) {
        switch (opt) {
        case 'o':
            g_output_dir = optarg;
            break;
        case 't':
            if (!g_table_list) {
                g_table_list = (char**)malloc(sizeof(char*) * 100);
            }
            g_table_list[g_table_count] = strdup(optarg);
            g_table_count++;
            g_export_all = 0;
            break;
        case 'd':
            g_delimiter = optarg[0];
            break;
        case 'H':
            g_write_header = 1;
            break;
        case 'T':
            g_write_types = 1;
            break;
        case 'a':
            g_export_all = 1;
            break;
        case 'h':
            print_usage(argv[0]);
            return EXIT_SUCCESS;
        default:
            print_usage(argv[0]);
            return EXIT_FAILURE;
        }
    }
    
    /* Check if dump file is specified */
    if (optind >= argc) {
        fprintf(stderr, "Error: Dump file not specified\n\n");
        print_usage(argv[0]);
        return EXIT_FAILURE;
    }
    
    dump_file = argv[optind];
    
    /* Check if file exists */
    FILE *test = fopen(dump_file, "rb");
    if (!test) {
        fprintf(stderr, "Error: Cannot open dump file: %s\n", dump_file);
        return EXIT_FAILURE;
    }
    fclose(test);
    
    printf("========================================\n");
    printf("OraDB DUMP Viewer - CSV Export Tool\n");
    printf("Version: %s\n", odv_get_version());
    printf("========================================\n");
    printf("Dump file: %s\n", dump_file);
    printf("Output directory: %s\n", g_output_dir);
    printf("CSV delimiter: '%c'\n", g_delimiter);
    printf("Write header: %s\n", g_write_header ? "Yes" : "No");
    printf("Write types: %s\n", g_write_types ? "Yes" : "No");
    printf("========================================\n\n");
    
    /* Export tables */
    if (g_export_all) {
        export_all_tables(dump_file, g_output_dir);
    } else if (g_table_count > 0) {
        export_selected_tables(dump_file, g_output_dir, g_table_list, g_table_count);
    } else {
        fprintf(stderr, "Error: No tables specified for export\n");
        return EXIT_FAILURE;
    }
    
    /* Cleanup */
    if (g_table_list) {
        for (int i = 0; i < g_table_count; i++) {
            free(g_table_list[i]);
        }
        free(g_table_list);
    }
    
    printf("\nFinal results: %d succeeded, %d failed\n", 
           g_export_success_count, g_export_fail_count);
    
    return (g_export_fail_count > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
}

输出

复制代码
./dmp2csv2 /par/exptest.dmp -o out3
========================================
OraDB DUMP Viewer - CSV Export Tool
Version: 3.1.0
========================================
Dump file: /par/exptest.dmp
Output directory: out3
CSV delimiter: ','
Write header: Yes
Write types: No
========================================

Phase 1: Listing tables in /par/exptest.dmp
----------------------------------------
  Found table: IGNORE (schema: EXPTEST, columns: 1, rows: 0)
  Found table: IGNORE2 (schema: EXPTEST, columns: 2, rows: 0)
  Found table: TABLE1 (schema: EXPTEST, columns: 7, rows: 0)
  Found table: TABLE2 (schema: EXPTEST, columns: 3, rows: 4)

Found 4 tables

Phase 2: Exporting tables to CSV
----------------------------------------
  [1/4] Exporting table: IGNORE -> out3/IGNORE.csv
    SUCCESS: 0 bytes, 0 rows
  [2/4] Exporting table: IGNORE2 -> out3/IGNORE2.csv
    SUCCESS: 0 bytes, 0 rows
  [3/4] Exporting table: TABLE1 -> out3/TABLE1.csv
    SUCCESS: 0 bytes, 0 rows
  [4/4] Exporting table: TABLE2 -> out3/TABLE2.csv
    SUCCESS: 64 bytes, 4 rows

Export completed: 4/4 tables exported successfully.

Final results: 4 succeeded, 0 failed

schema.sql

复制代码
-- Oracle DMP Schema Export
-- Generated by OraDB Dump Viewer
-- Export time: Apr  7 2026 11:49:08


-- Table: IGNORE
CREATE TABLE "IGNORE" ("COLUMN1" VARCHAR2(20));

-- Table: IGNORE2
CREATE TABLE "IGNORE2" ("COLUMN1" VARCHAR2(20), "COLUMN2" VARCHAR2(21));

-- Table: TABLE1
CREATE TABLE "TABLE1" ("KEYCOL" NUMBER(*,0) NOT NULL ENABLE, "NUMCOL1" NUMBER(22, 0), "FLOATCOL1" FLOAT(126), "STRCOL1" VARCHAR2(200), "DATECOL1" DATE, "BLOBCOL1" BLOB, "TIMESTAMP1" TIMESTAMP (6));

-- Table: TABLE2
CREATE TABLE "TABLE2" ("STRKEY" VARCHAR2(20) NOT NULL ENABLE, "FLOAT1" FLOAT(126), "DEC1" NUMBER(22, 5));

TABLE2.csv

复制代码
STRKEY,FLOAT1,DEC1
K1,1,14
K2,0.2,2.99992
K3,-0.3,-0.00232
K4,,
相关推荐
qq_429499572 小时前
更新SD卡文件列表到tablew中的list
windows
DREW_Smile2 小时前
自定义类型:联合体和枚举
c语言·开发语言
雨浓YN2 小时前
OPC DA 通讯开发笔记
windows·笔记
算法鑫探2 小时前
显示器插座最短连线算法(蓝桥杯十六届C组编程题第二题)
c语言·数据结构·算法·排序算法·新人首发
女王大人万岁2 小时前
Golang实战gRPC与Protobuf:从入门到进阶
服务器·开发语言·后端·qt·golang
时寒的笔记2 小时前
js基础05_js类、原型对象、原型链&案例(解决无限debugger)
开发语言·javascript·原型模式
人间打气筒(Ada)2 小时前
「码动四季·开源同行」go语言:如何使用 ELK 进行日志采集以及统一处理?
开发语言·分布式·elk·go·日志收集·分布式日志系统
波波0072 小时前
每日一题:C#中using的三种用法
开发语言·c#
游乐码2 小时前
c#万物之父
开发语言·c#